From 39d2adbbd0bde687ff768753aeaea98691788bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 31 Oct 2012 09:26:55 +0100 Subject: [PATCH 01/76] Added (skeleton) ecp.[ch] --- include/polarssl/config.h | 12 ++++ include/polarssl/ecp.h | 136 ++++++++++++++++++++++++++++++++++++++ library/CMakeLists.txt | 1 + library/ecp.c | 52 +++++++++++++++ 4 files changed, 201 insertions(+) create mode 100644 include/polarssl/ecp.h create mode 100644 library/ecp.c diff --git a/include/polarssl/config.h b/include/polarssl/config.h index dac70e715..2493233b9 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -829,6 +829,18 @@ * Caller: */ #define POLARSSL_XTEA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_ECP_C /* \} name */ #endif /* config.h */ diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h new file mode 100644 index 000000000..a616e1663 --- /dev/null +++ b/include/polarssl/ecp.h @@ -0,0 +1,136 @@ +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + * + * Copyright (C) 2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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 + */ + +/** + * \brief ECP point structure (affine coordinates) + */ +typedef struct +{ + mpi X; /*!< the point's X coordinate */ + mpi Y; /*!< the point's Y coordinate */ +} +ecp_point; + +/** + * \brief ECP group structure + * + * The curves we consider are defined by y^2 = x^3 - 3x + b mod p, + * and a generator for a large subgroup is fixed. + */ +typedef struct +{ + mpi P; /*!< prime modulus of the base field */ + mpi B; /*!< constant term in the equation */ + ecp_point G; /*!< generator of the subgroup used */ + mpi N; /*!< the order of G */ + unsigned char h; /*!< the cofactor of the subgroup */ +} +ecp_group; + +/** + * RFC 5114 defines a number of standardized ECP groups for use with TLS. + * + * These also are the NIST-recommended ECP groups, are the random ECP groups + * recommended by SECG, and include the two groups used by NSA Suite B. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources (such as the ones below) should be used. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \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, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecp_add( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ); + +/** + * \brief Duplication: R = 2 P + * + * \param grp ECP group + * \param R Destination point + * \param P Point to double + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecp_double( const ecp_group *grp, ecp_point *R, + const ecp_point *P ); + +/** + * \brief Multiplication by an integer: R = m * P + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecp_multiply( const ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P ); + +/** + * \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 Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecp_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index aae1f509a..704a4b08f 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -16,6 +16,7 @@ set(src debug.c des.c dhm.c + ecp.c entropy.c entropy_poll.c error.c diff --git a/library/ecp.c b/library/ecp.c new file mode 100644 index 000000000..1caf0c6dd --- /dev/null +++ b/library/ecp.c @@ -0,0 +1,52 @@ +/* + * Elliptic curves over GF(p) + * + * Copyright (C) 2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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-v2 (XXX: insert url) + * Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_ECP_C) + +#include "polarssl/ecp.h" + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecp_self_test( int verbose ) +{ + return( verbose++ ); +} + +#endif + +#endif From d7e4570ad17b8546fe1a8baff9b425e358f33eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 31 Oct 2012 18:57:05 +0100 Subject: [PATCH 02/76] Copied ECP parameters from RFC 5114 --- include/polarssl/ecp.h | 71 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index a616e1663..d9e6ed635 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -55,7 +55,6 @@ typedef struct mpi B; /*!< constant term in the equation */ ecp_point G; /*!< generator of the subgroup used */ mpi N; /*!< the order of G */ - unsigned char h; /*!< the cofactor of the subgroup */ } ecp_group; @@ -64,11 +63,81 @@ ecp_group; * * These also are the NIST-recommended ECP groups, are the random ECP groups * recommended by SECG, and include the two groups used by NSA Suite B. + * There are known as secpLLLr1 with LLL = 192, 224, 256, 384, 521. * * \warning This library does not support validation of arbitrary domain * parameters. Therefore, only well-known domain parameters from trusted * sources (such as the ones below) should be used. */ +#define POLARSSL_ECP_SECP192R1_P \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF" +#define POLARSSL_ECP_SECP192R1_B \ + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1" +#define POLARSSL_ECP_SECP192R1_GX \ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" +#define POLARSSL_ECP_SECP192R1_GY \ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811" +#define POLARSSL_ECP_SECP192R1_N \ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831" + +#define POLARSSL_ECP_SECP224R1_P \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001" +#define POLARSSL_ECP_SECP224R1_B \ + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4" +#define POLARSSL_ECP_SECP224R1_GX \ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" +#define POLARSSL_ECP_SECP224R1_GY \ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34" +#define POLARSSL_ECP_SECP224R1_N \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D" + +#define POLARSSL_ECP_SECP256R1_P \ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" +#define POLARSSL_ECP_SECP256R1_B \ + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B" +#define POLARSSL_ECP_SECP256R1_GX \ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" +#define POLARSSL_ECP_SECP256R1_GY \ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" +#define POLARSSL_ECP_SECP256R1_N \ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551" + +#define POLARSSL_ECP_SECP384R1_P \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF" +#define POLARSSL_ECP_SECP384R1_B \ + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE814112" \ + "0314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF" +#define POLARSSL_ECP_SECP384R1_GX \ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B98" \ + "59F741E082542A385502F25DBF55296C3A545E3872760AB7" +#define POLARSSL_ECP_SECP384R1_GY \ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147C" \ + "E9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F" +#define POLARSSL_ECP_SECP384R1_N \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "C7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973" + +#define POLARSSL_ECP_SECP521R1_P \ + "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +#define POLARSSL_ECP_SECP521R1_B \ + "00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B" \ + "99B315F3B8B489918EF109E156193951EC7E937B1652C0BD" \ + "3BB1BF073573DF883D2C34F1EF451FD46B503F00" +#define POLARSSL_ECP_SECP521R1_GX \ + "000000C6858E06B70404E9CD9E3ECB662395B4429C648139" \ + "053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127" \ + "A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" +#define POLARSSL_ECP_SECP521R1_GY \ + "0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449" \ + "579B446817AFBD17273E662C97EE72995EF42640C550B901" \ + "3FAD0761353C7086A272C24088BE94769FD16650" +#define POLARSSL_ECP_SECP521R1_N \ + "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148" \ + "F709A5D03BB5C9B8899C47AEBB6FB71E91386409" #ifdef __cplusplus extern "C" { From 1e8c8ecd9509121e6a024c564373a6cb4be82392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 31 Oct 2012 19:24:21 +0100 Subject: [PATCH 03/76] Implemented ecp_{point,group}_free() --- library/ecp.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/ecp.c b/library/ecp.c index 1caf0c6dd..7f157377f 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -36,6 +36,31 @@ #include "polarssl/ecp.h" +/* + * 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 ) ); +} + +/* + * Unallocate (the components of) a group + */ +void ecp_group_free( ecp_group *grp ) +{ + if( grp == NULL ) + return; + + mpi_free( &( grp->P ) ); + mpi_free( &( grp->B ) ); + mpi_free( &( grp->N ) ); + ecp_point_free( &( grp->G ) ); +} #if defined(POLARSSL_SELF_TEST) From 5179e463d5c7d3e542eb3797ddaf9cbfe176784a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 31 Oct 2012 19:37:54 +0100 Subject: [PATCH 04/76] Allowed point at infinity, supressed ecp_double() --- include/polarssl/ecp.h | 21 +++++---------------- library/ecp.c | 3 +++ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index d9e6ed635..e76cd9eb0 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -38,8 +38,9 @@ */ typedef struct { - mpi X; /*!< the point's X coordinate */ - mpi Y; /*!< the point's Y coordinate */ + char is_zero; /*!< true if point at infinity */ + mpi X; /*!< the point's X coordinate */ + mpi Y; /*!< the point's Y coordinate */ } ecp_point; @@ -156,18 +157,6 @@ extern "C" { int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ); -/** - * \brief Duplication: R = 2 P - * - * \param grp ECP group - * \param R Destination point - * \param P Point to double - * - * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code - */ -int ecp_double( const ecp_group *grp, ecp_point *R, - const ecp_point *P ); - /** * \brief Multiplication by an integer: R = m * P * @@ -178,8 +167,8 @@ int ecp_double( const ecp_group *grp, ecp_point *R, * * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code */ -int ecp_multiply( const ecp_group *grp, ecp_point *R, - const mpi *m, const ecp_point *P ); +int ecp_mul( const ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P ); /** * \brief Free the components of a point diff --git a/library/ecp.c b/library/ecp.c index 7f157377f..2173e2484 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -44,6 +44,7 @@ void ecp_point_free( ecp_point *pt ) if( pt == NULL ) return; + pt->is_zero = 1; mpi_free( &( pt->X ) ); mpi_free( &( pt->Y ) ); } @@ -62,6 +63,8 @@ void ecp_group_free( ecp_group *grp ) ecp_point_free( &( grp->G ) ); } + + #if defined(POLARSSL_SELF_TEST) /* From 883f313516ad0c797c9e9394e0c3028241ac2bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 2 Nov 2012 09:40:25 +0100 Subject: [PATCH 05/76] Added ecp_copy() (for points) --- include/polarssl/ecp.h | 31 +++++++++++++++++++++---------- library/ecp.c | 24 +++++++++++++++++++----- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index e76cd9eb0..23d3fbd68 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -33,6 +33,7 @@ * ECP Error codes */ + /** * \brief ECP point structure (affine coordinates) */ @@ -144,6 +145,26 @@ ecp_group; extern "C" { #endif +/** + * \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 Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecp_copy( ecp_point *P, const ecp_point *Q ); + /** * \brief Addition: R = P + Q * @@ -170,16 +191,6 @@ int ecp_add( const ecp_group *grp, ecp_point *R, int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); -/** - * \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 Checkup routine * diff --git a/library/ecp.c b/library/ecp.c index 2173e2484..6c3b4a8b4 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -26,7 +26,7 @@ /* * References: * - * SEC1-v2 (XXX: insert url) + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg * Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone */ @@ -57,12 +57,26 @@ void ecp_group_free( ecp_group *grp ) if( grp == NULL ) return; - mpi_free( &( grp->P ) ); - mpi_free( &( grp->B ) ); - mpi_free( &( grp->N ) ); - ecp_point_free( &( grp->G ) ); + mpi_free( &grp->P ); + mpi_free( &grp->B ); + ecp_point_free( &grp->G ); + mpi_free( &grp->N ); } +/* + * Copy the contents of Q into P + */ +int ecp_copy( ecp_point *P, const ecp_point *Q ) +{ + int ret; + + P->is_zero = Q->is_zero; + MPI_CHK( mpi_copy( &P->X, &Q->X ) ); + MPI_CHK( mpi_copy( &P->Y, &Q->Y ) ); + +cleanup: + return( ret ); +} #if defined(POLARSSL_SELF_TEST) From ae180d0f206d3a23cf02e96199ad767585414c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 2 Nov 2012 18:14:40 +0100 Subject: [PATCH 06/76] Got started on ecp_add(): generic case done --- include/polarssl/ecp.h | 12 ++++ library/ecp.c | 133 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 23d3fbd68..1321de1b6 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -36,6 +36,8 @@ /** * \brief ECP point structure (affine coordinates) + * + * Note: if the point is zero, X and Y are irrelevant and should be freed. */ typedef struct { @@ -145,6 +147,11 @@ ecp_group; extern "C" { #endif +/** + * \brief Initialize a point + */ +void ecp_point_init( ecp_point *pt ); + /** * \brief Free the components of a point */ @@ -155,6 +162,11 @@ void ecp_point_free( ecp_point *pt ); */ void ecp_group_free( ecp_group *grp ); +/** + * \brief Set a point to zero + */ +void ecp_set_zero( ecp_point *pt ); + /** * \brief Copy the contents of point Q into P * diff --git a/library/ecp.c b/library/ecp.c index 6c3b4a8b4..825db991e 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -36,6 +36,19 @@ #include "polarssl/ecp.h" +/* + * Initialize a point + */ +void ecp_point_init( ecp_point *pt ) +{ + if( pt == NULL ) + return; + + pt->is_zero = 1; + mpi_init( &( pt->X ) ); + mpi_init( &( pt->Y ) ); +} + /* * Unallocate (the components of) a point */ @@ -63,12 +76,22 @@ void ecp_group_free( ecp_group *grp ) mpi_free( &grp->N ); } +/* + * Set point to zero + */ +void ecp_set_zero( ecp_point *pt ) +{ + pt->is_zero = 1; + mpi_free( &( pt->X ) ); + mpi_free( &( pt->Y ) ); +} + /* * Copy the contents of Q into P */ int ecp_copy( ecp_point *P, const ecp_point *Q ) { - int ret; + int ret = 0; P->is_zero = Q->is_zero; MPI_CHK( mpi_copy( &P->X, &Q->X ) ); @@ -78,6 +101,114 @@ cleanup: return( ret ); } +/* + * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) + * Cf SEC1 v2 p. 7, item 4 + */ +static int ecp_add_generic( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret = 0; + mpi DX, DY, K, L, LL, M, X, Y; + + mpi_init( &DX ); mpi_init( &DY ); mpi_init( &K ); mpi_init( &L ); + mpi_init( &LL ); mpi_init( &M ); mpi_init( &X ); mpi_init( &Y ); + + /* + * L = (Q.Y - P.Y) / (Q.X - P.X) mod p + */ + MPI_CHK( mpi_sub_mpi( &DY, &Q->Y, &P->Y ) ); + MPI_CHK( mpi_sub_mpi( &DX, &Q->X, &P->X ) ); + MPI_CHK( mpi_inv_mod( &K, &DX, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &K, &K, &DY ) ); + MPI_CHK( mpi_mod_mpi( &L, &K, &grp->P ) ); + + /* + * LL = L^2 mod p + * M = L^2 - Q.X + * X = L^2 - P.X - Q.X + */ + MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) ); + MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) ); + MPI_CHK( mpi_sub_mpi( &M, &LL, &Q->X ) ); + MPI_CHK( mpi_sub_mpi( &X, &M, &P->X ) ); + + /* + * Y = L * (P.X - X) - P.Y = L * (-M) - P.Y + */ + MPI_CHK( mpi_copy( &Y, &M ) ); + Y.s = - Y.s; + MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) ); + MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) ); + + /* + * R = (X mod p, Y mod p) + */ + R->is_zero = 0; + MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) ); + MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); + +cleanup: + + mpi_free( &DX ); mpi_free( &DY ); mpi_free( &K ); mpi_free( &L ); + mpi_free( &LL ); mpi_free( &M ); mpi_free( &X ); mpi_free( &Y ); + + return( ret ); +} + +/* + * Doubling: R = 2 * P, generic case (P != 0, R != 0) + * + * Returns POLARSSL_ERR_MPI_XXX on error. + */ +static int ecp_double_generic( const ecp_group *grp, ecp_point *R, + const ecp_point *P ) +{ + int ret = 0; + + (void) grp; + (void) R; + (void) P; + + return( ret ); +} + +/* + * Addition: R = P + Q, cf p. 7 of SEC1 v2 + */ +int ecp_add( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret = 0; + + if( P->is_zero ) + { + ret = ecp_copy( R, Q ); + } + else if( Q->is_zero ) + { + ret = ecp_copy( R, P ); + } + else if( mpi_cmp_mpi( &P->X, &Q->X ) != 0 ) + { + ret = ecp_add_generic( grp, R, P, Q ); + } + else if( mpi_cmp_int( &P->Y, 0 ) == 0 || + mpi_cmp_mpi( &P->Y, &Q->Y ) != 0 ) + { + ecp_set_zero( R ); + } + else + { + /* + * P == Q + */ + ret = ecp_double_generic( grp, R, P ); + } + + return ret; +} + #if defined(POLARSSL_SELF_TEST) From 7cfcea349ce5ddd2fb0dd31226e0b8ab9e2e68f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 5 Nov 2012 10:06:12 +0100 Subject: [PATCH 07/76] Documented error codes properly --- include/polarssl/ecp.h | 19 +++++++++++++++---- library/ecp.c | 2 -- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 1321de1b6..841bf5e1c 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -30,7 +30,9 @@ #include "bignum.h" /* - * ECP Error codes + * ECP error codes + * + * (The functions written up to now return MPI error codes only.) */ @@ -173,7 +175,8 @@ void ecp_set_zero( ecp_point *pt ); * \param P Destination point * \param Q Source point * - * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed */ int ecp_copy( ecp_point *P, const ecp_point *Q ); @@ -185,7 +188,11 @@ int ecp_copy( ecp_point *P, const ecp_point *Q ); * \param P Left-hand point * \param Q Right-hand point * - * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO (shouldn't happen) + * (temporary, a faster version not using division will be + * used in the furture) */ int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ); @@ -198,7 +205,11 @@ int ecp_add( const ecp_group *grp, ecp_point *R, * \param m Integer by which to multiply * \param P Point to multiply * - * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO (shouldn't happen) + * (temporary, a faster version not using division will be + * used in the furture) */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); diff --git a/library/ecp.c b/library/ecp.c index 825db991e..141c13ad1 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -158,8 +158,6 @@ cleanup: /* * Doubling: R = 2 * P, generic case (P != 0, R != 0) - * - * Returns POLARSSL_ERR_MPI_XXX on error. */ static int ecp_double_generic( const ecp_group *grp, ecp_point *R, const ecp_point *P ) From 847395a8a967e64790a80af48336060be0e69c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 5 Nov 2012 13:13:44 +0100 Subject: [PATCH 08/76] Added ecp_XXX_read_string() --- include/polarssl/ecp.h | 32 +++++++++++++++++++++++++++++++- library/ecp.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 841bf5e1c..805e7b022 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -150,7 +150,7 @@ extern "C" { #endif /** - * \brief Initialize a point + * \brief Initialize a point (as zero) */ void ecp_point_init( ecp_point *pt ); @@ -180,6 +180,36 @@ void ecp_set_zero( ecp_point *pt ); */ int ecp_copy( ecp_point *P, const ecp_point *Q ); +/** + * \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 Import an ECP group from null-terminated ASCII strings + * + * \param grp Destination group + * \param radix Input numric 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 + */ +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 Addition: R = P + Q * diff --git a/library/ecp.c b/library/ecp.c index 141c13ad1..f7c839d15 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -101,6 +101,40 @@ cleanup: return( ret ); } +/* + * 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 = 0; + + P->is_zero = 0; + MPI_CHK( mpi_read_string( &P->X, radix, x ) ); + MPI_CHK( mpi_read_string( &P->Y, radix, y ) ); + +cleanup: + return( ret ); +} + +/* + * Import an ECP group from ASCII strings + */ +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 = 0; + + 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 ) ); + +cleanup: + return( ret ); +} + /* * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) * Cf SEC1 v2 p. 7, item 4 From d0dc6317e199d6dd99c467eec54f0f4d6142e224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 5 Nov 2012 16:28:33 +0100 Subject: [PATCH 09/76] Added a few test cases for addition --- library/ecp.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/library/ecp.c b/library/ecp.c index f7c839d15..a249ac565 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -244,12 +244,77 @@ int ecp_add( const ecp_group *grp, ecp_point *R, #if defined(POLARSSL_SELF_TEST) +/* + * Return true iff P and Q are the same point + */ +static int ecp_point_eq( const ecp_point *P, const ecp_point *Q ) +{ + if( P->is_zero || Q->is_zero ) + return( P->is_zero && Q->is_zero ); + + return( mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 ); +} + /* * Checkup routine + * + * Data gathered from http://danher6.100webspace.net/ecc/#EFp_interactivo + * and double-checked using Pari-GP */ int ecp_self_test( int verbose ) { - return( verbose++ ); + int ret = 0; + size_t i; + ecp_group grp; + ecp_point O, A, B, C, D, E, F, G, TMP; + ecp_point add_table[][3] = + { + {O, O, O}, {O, A, A}, {A, O, A}, + {A, A, O}, {B, C, O}, {C, B, O}, + {A, D, E}, {D, A, E}, {B, D, F}, {D, B, F}, + {D, D, G}, + }; + + ecp_set_zero( &O ); + MPI_CHK( ecp_group_read_string( &grp, 10, "47", "4", "17", "42", "13" ) ); + MPI_CHK( ecp_point_read_string( &A, 10, "13", "0" ) ); + MPI_CHK( ecp_point_read_string( &B, 10, "14", "11" ) ); + MPI_CHK( ecp_point_read_string( &C, 10, "14", "36" ) ); + MPI_CHK( ecp_point_read_string( &D, 10, "37", "31" ) ); + MPI_CHK( ecp_point_read_string( &E, 10, "34", "14" ) ); + MPI_CHK( ecp_point_read_string( &F, 10, "45", "7" ) ); + MPI_CHK( ecp_point_read_string( &E, 10, "21", "32" ) ); + + if( verbose != 0 ) + printf( " ECP test #1 (ecp_add): " ); + + for( i = 0; i < sizeof( add_table ) / sizeof( add_table[0] ); i++ ) + { + MPI_CHK( ecp_add( &grp, &TMP, &add_table[i][0], &add_table[i][1] ) ); + if( ! ecp_point_eq( &TMP, &add_table[i][2] ) ) + { + if( verbose != 0 ) + printf(" failed (%zu)\n", i); + + return( 1 ); + } + } + +cleanup: + + if( ret != 0 && verbose != 0 ) + printf( "Unexpected error, return code = %08X\n", ret ); + + ecp_group_free( &grp ); + ecp_point_free( &O ); ecp_point_free( &A ); ecp_point_free( &B ); + ecp_point_free( &C ); ecp_point_free( &D ); ecp_point_free( &E ); + ecp_point_free( &F ); ecp_point_free( &G ); + + if( verbose != 0 ) + printf( "\n" ); + + return( ret ); } #endif From b505c2796c2aaacc4ab999066871b20263aa01a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 5 Nov 2012 17:27:54 +0100 Subject: [PATCH 10/76] Got first tests working, fixed ecp_copy() --- include/polarssl/ecp.h | 11 ++++-- library/ecp.c | 79 +++++++++++++++++++++++++++++++--------- programs/test/selftest.c | 5 +++ 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 805e7b022..2bede2ca8 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -154,6 +154,11 @@ extern "C" { */ void ecp_point_init( ecp_point *pt ); +/** + * \brief Initialize a group (to something meaningless) + */ +void ecp_group_init( ecp_group *grp ); + /** * \brief Free the components of a point */ @@ -197,7 +202,7 @@ int ecp_point_read_string( ecp_point *P, int radix, * \brief Import an ECP group from null-terminated ASCII strings * * \param grp Destination group - * \param radix Input numric base + * \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 @@ -222,7 +227,7 @@ int ecp_group_read_string( ecp_group *grp, int radix, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, * POLARSSL_ERR_MPI_DIVISION_BY_ZERO (shouldn't happen) * (temporary, a faster version not using division will be - * used in the furture) + * used in the future) */ int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ); @@ -239,7 +244,7 @@ int ecp_add( const ecp_group *grp, ecp_point *R, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, * POLARSSL_ERR_MPI_DIVISION_BY_ZERO (shouldn't happen) * (temporary, a faster version not using division will be - * used in the furture) + * used in the future) */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); diff --git a/library/ecp.c b/library/ecp.c index a249ac565..242316b1a 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -37,7 +37,7 @@ #include "polarssl/ecp.h" /* - * Initialize a point + * Initialize (the components of) a point */ void ecp_point_init( ecp_point *pt ) { @@ -45,8 +45,22 @@ void ecp_point_init( ecp_point *pt ) return; pt->is_zero = 1; - mpi_init( &( pt->X ) ); - mpi_init( &( pt->Y ) ); + mpi_init( &pt->X ); + mpi_init( &pt->Y ); +} + +/* + * Initialize (the components of) a group + */ +void ecp_group_init( ecp_group *grp ) +{ + if( grp == NULL ) + return; + + mpi_init( &grp->P ); + mpi_init( &grp->B ); + ecp_point_init( &grp->G ); + mpi_init( &grp->N ); } /* @@ -82,8 +96,8 @@ void ecp_group_free( ecp_group *grp ) void ecp_set_zero( ecp_point *pt ) { pt->is_zero = 1; - mpi_free( &( pt->X ) ); - mpi_free( &( pt->Y ) ); + mpi_free( &pt->X ); + mpi_free( &pt->Y ); } /* @@ -93,6 +107,11 @@ int ecp_copy( ecp_point *P, const ecp_point *Q ) { int ret = 0; + if( Q->is_zero ) { + ecp_set_zero( P ); + return( ret ); + } + P->is_zero = Q->is_zero; MPI_CHK( mpi_copy( &P->X, &Q->X ) ); MPI_CHK( mpi_copy( &P->Y, &Q->Y ) ); @@ -256,26 +275,41 @@ static int ecp_point_eq( const ecp_point *P, const ecp_point *Q ) mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 ); } +/* + * Print a point assuming its components are small + */ +static void ecp_point_print( const ecp_point *P ) +{ + if( P->is_zero ) + printf("zero\n"); + else + printf("(%lu, %lu)\n", P->X.p[0], P->Y.p[0]); +} + + /* * Checkup routine * - * Data gathered from http://danher6.100webspace.net/ecc/#EFp_interactivo - * and double-checked using Pari-GP + * Data for basic tests with small values gathered from + * http://danher6.100webspace.net/ecc/#EFp_interactivo and double-checked + * using Pari-GP. */ int ecp_self_test( int verbose ) { int ret = 0; - size_t i; + unsigned i; ecp_group grp; ecp_point O, A, B, C, D, E, F, G, TMP; - ecp_point add_table[][3] = + ecp_point *add_tbl[][3] = { - {O, O, O}, {O, A, A}, {A, O, A}, - {A, A, O}, {B, C, O}, {C, B, O}, - {A, D, E}, {D, A, E}, {B, D, F}, {D, B, F}, - {D, D, G}, + {&O, &O, &O}, }; + ecp_group_init( &grp ); + ecp_point_init( &O ); ecp_point_init( &A ); ecp_point_init( &B ); + ecp_point_init( &C ); ecp_point_init( &D ); ecp_point_init( &E ); + ecp_point_init( &F ); ecp_point_init( &G ); ecp_point_init( &TMP ); + ecp_set_zero( &O ); MPI_CHK( ecp_group_read_string( &grp, 10, "47", "4", "17", "42", "13" ) ); MPI_CHK( ecp_point_read_string( &A, 10, "13", "0" ) ); @@ -284,23 +318,32 @@ int ecp_self_test( int verbose ) MPI_CHK( ecp_point_read_string( &D, 10, "37", "31" ) ); MPI_CHK( ecp_point_read_string( &E, 10, "34", "14" ) ); MPI_CHK( ecp_point_read_string( &F, 10, "45", "7" ) ); - MPI_CHK( ecp_point_read_string( &E, 10, "21", "32" ) ); + MPI_CHK( ecp_point_read_string( &G, 10, "21", "32" ) ); if( verbose != 0 ) printf( " ECP test #1 (ecp_add): " ); - for( i = 0; i < sizeof( add_table ) / sizeof( add_table[0] ); i++ ) + for( i = 0; i < sizeof( add_tbl ) / sizeof( add_tbl[0] ); i++ ) { - MPI_CHK( ecp_add( &grp, &TMP, &add_table[i][0], &add_table[i][1] ) ); - if( ! ecp_point_eq( &TMP, &add_table[i][2] ) ) + MPI_CHK( ecp_add( &grp, &TMP, add_tbl[i][0], add_tbl[i][1] ) ); + if( ! ecp_point_eq( &TMP, add_tbl[i][2] ) ) { if( verbose != 0 ) - printf(" failed (%zu)\n", i); + { + printf(" failed\n"); + printf(" GOT: "); + ecp_point_print( &TMP ); + printf(" EXPECTED: "); + ecp_point_print( add_tbl[i][2] ); + } return( 1 ); } } + if (verbose != 0 ) + printf( " passed\n" ); + cleanup: if( ret != 0 && verbose != 0 ) diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 8dddf3481..98cc90ca3 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -155,6 +155,11 @@ int main( int argc, char *argv[] ) return( ret ); #endif +#if defined(POLARSSL_ECP_C) + if( ( ret = ecp_self_test( v ) ) != 0 ) + return( ret ); +#endif + #else printf( " POLARSSL_SELF_TEST not defined.\n" ); #endif From ab38b7081621e7da04a7929acaaed04e0de1c6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 5 Nov 2012 17:34:55 +0100 Subject: [PATCH 11/76] Fixed add_generic --- library/ecp.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 242316b1a..99d57cd4c 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -154,6 +154,8 @@ cleanup: return( ret ); } +#define dbg(X) printf(#X " = %s%lu\n", X.s < 0 ? "-" : "", X.p[0]) + /* * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) * Cf SEC1 v2 p. 7, item 4 @@ -162,10 +164,10 @@ static int ecp_add_generic( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ) { int ret = 0; - mpi DX, DY, K, L, LL, M, X, Y; + mpi DX, DY, K, L, LL, X, Y; mpi_init( &DX ); mpi_init( &DY ); mpi_init( &K ); mpi_init( &L ); - mpi_init( &LL ); mpi_init( &M ); mpi_init( &X ); mpi_init( &Y ); + mpi_init( &LL ); mpi_init( &X ); mpi_init( &Y ); /* * L = (Q.Y - P.Y) / (Q.X - P.X) mod p @@ -178,19 +180,21 @@ static int ecp_add_generic( const ecp_group *grp, ecp_point *R, /* * LL = L^2 mod p - * M = L^2 - Q.X * X = L^2 - P.X - Q.X */ MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) ); MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) ); - MPI_CHK( mpi_sub_mpi( &M, &LL, &Q->X ) ); - MPI_CHK( mpi_sub_mpi( &X, &M, &P->X ) ); /* - * Y = L * (P.X - X) - P.Y = L * (-M) - P.Y + * X = L^2 - P.X - Q.X */ - MPI_CHK( mpi_copy( &Y, &M ) ); - Y.s = - Y.s; + MPI_CHK( mpi_sub_mpi( &X, &LL, &P->X ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &Q->X ) ); + + /* + * Y = L * (P.X - X) - P.Y + */ + MPI_CHK( mpi_sub_mpi( &Y, &P->X, &X) ); MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) ); MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) ); @@ -204,7 +208,7 @@ static int ecp_add_generic( const ecp_group *grp, ecp_point *R, cleanup: mpi_free( &DX ); mpi_free( &DY ); mpi_free( &K ); mpi_free( &L ); - mpi_free( &LL ); mpi_free( &M ); mpi_free( &X ); mpi_free( &Y ); + mpi_free( &LL ); mpi_free( &X ); mpi_free( &Y ); return( ret ); } @@ -276,14 +280,14 @@ static int ecp_point_eq( const ecp_point *P, const ecp_point *Q ) } /* - * Print a point assuming its components are small + * Print a point assuming its coordinates are small */ static void ecp_point_print( const ecp_point *P ) { if( P->is_zero ) - printf("zero\n"); + printf( "zero\n" ); else - printf("(%lu, %lu)\n", P->X.p[0], P->Y.p[0]); + printf( "(%lu, %lu)\n", P->X.p[0], P->Y.p[0] ); } @@ -302,7 +306,11 @@ int ecp_self_test( int verbose ) ecp_point O, A, B, C, D, E, F, G, TMP; ecp_point *add_tbl[][3] = { - {&O, &O, &O}, + {&O, &O, &O}, {&O, &A, &A}, {&A, &O, &A}, + {&A, &A, &O}, {&B, &C, &O}, {&C, &B, &O}, + {&A, &D, &E}, {&D, &A, &E}, + {&B, &D, &F}, {&D, &B, &F}, + // {&D, &D, &G}, }; ecp_group_init( &grp ); @@ -330,10 +338,10 @@ int ecp_self_test( int verbose ) { if( verbose != 0 ) { - printf(" failed\n"); - printf(" GOT: "); + printf(" failed (%u)\n", i ); + printf( " GOT: " ); ecp_point_print( &TMP ); - printf(" EXPECTED: "); + printf( " EXPECTED: " ); ecp_point_print( add_tbl[i][2] ); } From de532ee73fb78a2b84067793ed031ab4f09e5997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 6 Nov 2012 16:10:47 +0100 Subject: [PATCH 12/76] Implemented generic doubling --- library/ecp.c | 67 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 99d57cd4c..857839afc 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -180,7 +180,6 @@ static int ecp_add_generic( const ecp_group *grp, ecp_point *R, /* * LL = L^2 mod p - * X = L^2 - P.X - Q.X */ MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) ); MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) ); @@ -215,15 +214,60 @@ cleanup: /* * Doubling: R = 2 * P, generic case (P != 0, R != 0) + * Cf SEC1 v2 p. 7, item 5 */ static int ecp_double_generic( const ecp_group *grp, ecp_point *R, const ecp_point *P ) { int ret = 0; + mpi LN, LD, K, L, LL, X, Y; - (void) grp; - (void) R; - (void) P; + mpi_init( &LN ); mpi_init( &LD ); mpi_init( &K ); mpi_init( &L ); + mpi_init( &LL ); mpi_init( &X ); mpi_init( &Y ); + + /* + * L = 3 (P.X - 1) (P.X + 1) / (2 P.Y) mod p + */ + MPI_CHK( mpi_copy( &LD, &P->Y ) ); + MPI_CHK( mpi_shift_l( &LD, 1 ) ); + MPI_CHK( mpi_inv_mod( &K, &LD, &grp->P ) ); + MPI_CHK( mpi_mul_int( &K, &K, 3 ) ); + MPI_CHK( mpi_sub_int( &LN, &P->X, 1 ) ); + MPI_CHK( mpi_mul_mpi( &K, &K, &LN ) ); + MPI_CHK( mpi_add_int( &LN, &P->X, 1 ) ); + MPI_CHK( mpi_mul_mpi( &K, &K, &LN ) ); + MPI_CHK( mpi_mod_mpi( &L, &K, &grp->P ) ); + + /* + * LL = L^2 mod p + */ + MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) ); + MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) ); + + /* + * X = L^2 - 2 * P.X + */ + MPI_CHK( mpi_sub_mpi( &X, &LL, &P->X ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &P->X ) ); + + /* + * Y = L * (P.X - X) - P.Y + */ + MPI_CHK( mpi_sub_mpi( &Y, &P->X, &X) ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) ); + MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) ); + + /* + * R = (X mod p, Y mod p) + */ + R->is_zero = 0; + MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) ); + MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); + +cleanup: + + mpi_free( &LN ); mpi_init( &LD ); mpi_init( &K ); mpi_init( &L ); + mpi_free( &LL ); mpi_init( &X ); mpi_init( &Y ); return( ret ); } @@ -264,7 +308,6 @@ int ecp_add( const ecp_group *grp, ecp_point *R, return ret; } - #if defined(POLARSSL_SELF_TEST) /* @@ -290,7 +333,6 @@ static void ecp_point_print( const ecp_point *P ) printf( "(%lu, %lu)\n", P->X.p[0], P->Y.p[0] ); } - /* * Checkup routine * @@ -303,20 +345,21 @@ int ecp_self_test( int verbose ) int ret = 0; unsigned i; ecp_group grp; - ecp_point O, A, B, C, D, E, F, G, TMP; + ecp_point O, A, B, C, D, E, F, G, H, TMP; ecp_point *add_tbl[][3] = { {&O, &O, &O}, {&O, &A, &A}, {&A, &O, &A}, {&A, &A, &O}, {&B, &C, &O}, {&C, &B, &O}, {&A, &D, &E}, {&D, &A, &E}, {&B, &D, &F}, {&D, &B, &F}, - // {&D, &D, &G}, + {&D, &D, &G}, {&B, &B, &H}, }; ecp_group_init( &grp ); ecp_point_init( &O ); ecp_point_init( &A ); ecp_point_init( &B ); ecp_point_init( &C ); ecp_point_init( &D ); ecp_point_init( &E ); - ecp_point_init( &F ); ecp_point_init( &G ); ecp_point_init( &TMP ); + ecp_point_init( &F ); ecp_point_init( &G ); ecp_point_init( &H ); + ecp_point_init( &TMP ); ecp_set_zero( &O ); MPI_CHK( ecp_group_read_string( &grp, 10, "47", "4", "17", "42", "13" ) ); @@ -327,6 +370,7 @@ int ecp_self_test( int verbose ) MPI_CHK( ecp_point_read_string( &E, 10, "34", "14" ) ); MPI_CHK( ecp_point_read_string( &F, 10, "45", "7" ) ); MPI_CHK( ecp_point_read_string( &G, 10, "21", "32" ) ); + MPI_CHK( ecp_point_read_string( &H, 10, "27", "30" ) ); if( verbose != 0 ) printf( " ECP test #1 (ecp_add): " ); @@ -350,7 +394,7 @@ int ecp_self_test( int verbose ) } if (verbose != 0 ) - printf( " passed\n" ); + printf( "passed\n" ); cleanup: @@ -360,7 +404,8 @@ cleanup: ecp_group_free( &grp ); ecp_point_free( &O ); ecp_point_free( &A ); ecp_point_free( &B ); ecp_point_free( &C ); ecp_point_free( &D ); ecp_point_free( &E ); - ecp_point_free( &F ); ecp_point_free( &G ); + ecp_point_free( &F ); ecp_point_free( &G ); ecp_point_free( &H ); + ecp_point_free( &TMP ); if( verbose != 0 ) printf( "\n" ); From b4ab8a813705e0216aaa014964f9476af0d6e0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 6 Nov 2012 18:13:32 +0100 Subject: [PATCH 13/76] Fixed memory leak due to typo --- library/ecp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 857839afc..bf570fe16 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -266,8 +266,8 @@ static int ecp_double_generic( const ecp_group *grp, ecp_point *R, cleanup: - mpi_free( &LN ); mpi_init( &LD ); mpi_init( &K ); mpi_init( &L ); - mpi_free( &LL ); mpi_init( &X ); mpi_init( &Y ); + mpi_free( &LN ); mpi_free( &LD ); mpi_free( &K ); mpi_free( &L ); + mpi_free( &LL ); mpi_free( &X ); mpi_free( &Y ); return( ret ); } From efaa31e9ae9394cbf0e59bd880708068702a1741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 6 Nov 2012 21:34:35 +0100 Subject: [PATCH 14/76] Implemented multiplication --- library/ecp.c | 155 +++++++++++++++++++++++++++++++++++---- programs/test/selftest.c | 1 + 2 files changed, 142 insertions(+), 14 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index bf570fe16..db69e42c0 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -308,8 +308,66 @@ int ecp_add( const ecp_group *grp, ecp_point *R, return ret; } +/* + * Integer multiplication: R = m * P + * Using Montgomery's Ladder to avoid leaking information about m + */ +int ecp_mul( const ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P ) +{ + int ret = 0; + size_t pos; + ecp_point A, B; + + ecp_point_init( &A ); ecp_point_init( &B ); + + /* + * The general method works only for m >= 2 + */ + if( mpi_cmp_int( m, 0 ) == 0 ) { + ecp_set_zero( R ); + goto cleanup; + } + + if( mpi_cmp_int( m, 1 ) == 0 ) { + MPI_CHK( ecp_copy( R, P ) ); + goto cleanup; + } + + MPI_CHK( ecp_copy( &A, P ) ); + MPI_CHK( ecp_add( grp, &B, P, P ) ); + + for( pos = mpi_msb( m ) - 2; ; pos-- ) + { + if( mpi_get_bit( m, pos ) == 0 ) + { + MPI_CHK( ecp_add( grp, &B, &A, &B ) ); + MPI_CHK( ecp_add( grp, &A, &A, &A ) ) ; + } + else + { + MPI_CHK( ecp_add( grp, &A, &A, &B ) ); + MPI_CHK( ecp_add( grp, &B, &B, &B ) ) ; + } + + if( pos == 0 ) + break; + } + + MPI_CHK( ecp_copy( R, &A ) ); + +cleanup: + + ecp_point_free( &A ); ecp_point_free( &B ); + + return( ret ); +} + + #if defined(POLARSSL_SELF_TEST) +#include "polarssl/error.h" + /* * Return true iff P and Q are the same point */ @@ -333,6 +391,8 @@ static void ecp_point_print( const ecp_point *P ) printf( "(%lu, %lu)\n", P->X.p[0], P->Y.p[0] ); } +#define TEST_GROUP_ORDER 13 + /* * Checkup routine * @@ -348,27 +408,50 @@ int ecp_self_test( int verbose ) ecp_point O, A, B, C, D, E, F, G, H, TMP; ecp_point *add_tbl[][3] = { - {&O, &O, &O}, {&O, &A, &A}, {&A, &O, &A}, - {&A, &A, &O}, {&B, &C, &O}, {&C, &B, &O}, - {&A, &D, &E}, {&D, &A, &E}, - {&B, &D, &F}, {&D, &B, &F}, - {&D, &D, &G}, {&B, &B, &H}, + { &O, &O, &O }, { &O, &A, &A }, { &A, &O, &A }, + { &A, &A, &O }, { &B, &C, &O }, { &C, &B, &O }, + { &A, &D, &E }, { &D, &A, &E }, + { &B, &D, &F }, { &D, &B, &F }, + { &D, &D, &G }, { &B, &B, &H }, + }; + mpi m; + ecp_point mul_tbl[TEST_GROUP_ORDER + 1]; + char *mul_tbl_s[TEST_GROUP_ORDER - 1][2] = + { + { "17", "42" }, + { "20", "01" }, + { "14", "11" }, + { "34", "33" }, + { "21", "32" }, + { "27", "30" }, + { "27", "17" }, + { "21", "15" }, + { "34", "14" }, + { "14", "36" }, + { "20", "46" }, + { "17", "05" }, }; ecp_group_init( &grp ); + ecp_point_init( &O ); ecp_point_init( &A ); ecp_point_init( &B ); ecp_point_init( &C ); ecp_point_init( &D ); ecp_point_init( &E ); ecp_point_init( &F ); ecp_point_init( &G ); ecp_point_init( &H ); ecp_point_init( &TMP ); + mpi_init( &m ); + + for( i = 0; i <= TEST_GROUP_ORDER; i++ ) + ecp_point_init( &mul_tbl[i] ); + ecp_set_zero( &O ); MPI_CHK( ecp_group_read_string( &grp, 10, "47", "4", "17", "42", "13" ) ); - MPI_CHK( ecp_point_read_string( &A, 10, "13", "0" ) ); + MPI_CHK( ecp_point_read_string( &A, 10, "13", "00" ) ); MPI_CHK( ecp_point_read_string( &B, 10, "14", "11" ) ); MPI_CHK( ecp_point_read_string( &C, 10, "14", "36" ) ); MPI_CHK( ecp_point_read_string( &D, 10, "37", "31" ) ); MPI_CHK( ecp_point_read_string( &E, 10, "34", "14" ) ); - MPI_CHK( ecp_point_read_string( &F, 10, "45", "7" ) ); + MPI_CHK( ecp_point_read_string( &F, 10, "45", "07" ) ); MPI_CHK( ecp_point_read_string( &G, 10, "21", "32" ) ); MPI_CHK( ecp_point_read_string( &H, 10, "27", "30" ) ); @@ -382,7 +465,7 @@ int ecp_self_test( int verbose ) { if( verbose != 0 ) { - printf(" failed (%u)\n", i ); + printf( " failed (%u)\n", i ); printf( " GOT: " ); ecp_point_print( &TMP ); printf( " EXPECTED: " ); @@ -396,16 +479,60 @@ int ecp_self_test( int verbose ) if (verbose != 0 ) printf( "passed\n" ); + MPI_CHK( ecp_copy( &mul_tbl[0], &O ) ); + for( i = 1; i <= TEST_GROUP_ORDER - 1; i++ ) + MPI_CHK( ecp_point_read_string( &mul_tbl[i], 10, + mul_tbl_s[i-1][0], mul_tbl_s[i-1][1] ) ); + MPI_CHK( ecp_copy( &mul_tbl[TEST_GROUP_ORDER], &O ) ); + + if( verbose != 0 ) + printf( " ECP test #2 (ecp_mul): " ); + + for( i = 0; i <= TEST_GROUP_ORDER; i++ ) + { + MPI_CHK( mpi_lset( &m, i ) ); + MPI_CHK( ecp_mul( &grp, &TMP, &m, &grp.G ) ); + if( ! ecp_point_eq( &TMP, &mul_tbl[i] ) ) + { + if( verbose != 0 ) + { + printf( " failed (%u)\n", i ); + printf( " GOT: " ); + ecp_point_print( &TMP ); + printf( " EXPECTED: " ); + ecp_point_print( &mul_tbl[i] ); + } + + return( 1 ); + } + } + + if (verbose != 0 ) + printf( "passed\n" ); + cleanup: if( ret != 0 && verbose != 0 ) - printf( "Unexpected error, return code = %08X\n", ret ); + { +#if defined(POLARSSL_ERROR_C) + char error_buf[200]; + error_strerror( ret, error_buf, 200 ); + printf( "Unexpected error: %d - %s\n\n", ret, error_buf ); +#else + printf( "Unexpected error: %08X\n", ret ); +#endif + } - ecp_group_free( &grp ); - ecp_point_free( &O ); ecp_point_free( &A ); ecp_point_free( &B ); - ecp_point_free( &C ); ecp_point_free( &D ); ecp_point_free( &E ); - ecp_point_free( &F ); ecp_point_free( &G ); ecp_point_free( &H ); - ecp_point_free( &TMP ); + ecp_group_free( &grp ); ecp_point_free( &O ); ecp_point_free( &TMP ); + + ecp_point_free( &A ); ecp_point_free( &B ); ecp_point_free( &C ); + ecp_point_free( &D ); ecp_point_free( &E ); ecp_point_free( &F ); + ecp_point_free( &G ); ecp_point_free( &H ); + + mpi_free( &m ); + + for( i = 0; i <= TEST_GROUP_ORDER; i++ ) + ecp_point_free( &mul_tbl[i] ); if( verbose != 0 ) printf( "\n" ); diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 98cc90ca3..333e3a16d 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -50,6 +50,7 @@ #include "polarssl/x509.h" #include "polarssl/xtea.h" #include "polarssl/pbkdf2.h" +#include "polarssl/ecp.h" int main( int argc, char *argv[] ) { From a5402fee04ce27c0c8e5783a1b8fb2a68034cb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 7 Nov 2012 20:24:05 +0100 Subject: [PATCH 15/76] Added ecp_use_known_dp() --- include/polarssl/ecp.h | 24 ++++++++++++-- include/polarssl/error.h | 1 + library/ecp.c | 68 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 2bede2ca8..8763fc18f 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -32,9 +32,9 @@ /* * ECP error codes * - * (The functions written up to now return MPI error codes only.) + * (Only one error code available...) */ - +#define POLARSSL_ERR_ECP_GENERIC -0x007E /**< Generic ECP error */ /** * \brief ECP point structure (affine coordinates) @@ -75,6 +75,12 @@ ecp_group; * parameters. Therefore, only well-known domain parameters from trusted * sources (such as the ones below) should be used. */ +#define POLARSSL_ECP_DP_SECP192R1 0 +#define POLARSSL_ECP_DP_SECP224R1 1 +#define POLARSSL_ECP_DP_SECP256R1 2 +#define POLARSSL_ECP_DP_SECP384R1 3 +#define POLARSSL_ECP_DP_SECP521R1 4 + #define POLARSSL_ECP_SECP192R1_P \ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF" #define POLARSSL_ECP_SECP192R1_B \ @@ -215,6 +221,20 @@ 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 O if successul, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_GENERIC if index is out of range + * + * \note Index should be a POLARSSL_ECP_DP_XXX macro. + */ +int ecp_use_known_dp( ecp_group *grp, size_t index ); + /** * \brief Addition: R = P + Q * diff --git a/include/polarssl/error.h b/include/polarssl/error.h index 96815a73a..736e8a795 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -68,6 +68,7 @@ * SHA2 1 0x0078-0x0078 * SHA4 1 0x007A-0x007A * PBKDF2 1 0x007C-0x007C + * ECP 1 0x007E-0x007E * * High-level module nr (3 bits - 0x1...-0x8...) * Name ID Nr of Errors diff --git a/library/ecp.c b/library/ecp.c index db69e42c0..ee3d6bfcc 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -154,7 +154,57 @@ cleanup: return( ret ); } -#define dbg(X) printf(#X " = %s%lu\n", X.s < 0 ? "-" : "", X.p[0]) +/* + * Set a group using well-known domain parameters + */ +int ecp_use_known_dp( ecp_group *grp, size_t index ) +{ + switch( index ) + { + case POLARSSL_ECP_DP_SECP192R1: + return( ecp_group_read_string( grp, 16, + POLARSSL_ECP_SECP192R1_P, + POLARSSL_ECP_SECP192R1_B, + POLARSSL_ECP_SECP192R1_GX, + POLARSSL_ECP_SECP192R1_GY, + POLARSSL_ECP_SECP192R1_N ) + ); + case POLARSSL_ECP_DP_SECP224R1: + return( ecp_group_read_string( grp, 16, + POLARSSL_ECP_SECP224R1_P, + POLARSSL_ECP_SECP224R1_B, + POLARSSL_ECP_SECP224R1_GX, + POLARSSL_ECP_SECP224R1_GY, + POLARSSL_ECP_SECP224R1_N ) + ); + case POLARSSL_ECP_DP_SECP256R1: + return( ecp_group_read_string( grp, 16, + POLARSSL_ECP_SECP256R1_P, + POLARSSL_ECP_SECP256R1_B, + POLARSSL_ECP_SECP256R1_GX, + POLARSSL_ECP_SECP256R1_GY, + POLARSSL_ECP_SECP256R1_N ) + ); + case POLARSSL_ECP_DP_SECP384R1: + return( ecp_group_read_string( grp, 16, + POLARSSL_ECP_SECP384R1_P, + POLARSSL_ECP_SECP384R1_B, + POLARSSL_ECP_SECP384R1_GX, + POLARSSL_ECP_SECP384R1_GY, + POLARSSL_ECP_SECP384R1_N ) + ); + case POLARSSL_ECP_DP_SECP521R1: + return( ecp_group_read_string( grp, 16, + POLARSSL_ECP_SECP521R1_P, + POLARSSL_ECP_SECP521R1_B, + POLARSSL_ECP_SECP521R1_GX, + POLARSSL_ECP_SECP521R1_GY, + POLARSSL_ECP_SECP521R1_N ) + ); + } + + return( POLARSSL_ERR_ECP_GENERIC ); +} /* * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) @@ -476,7 +526,7 @@ int ecp_self_test( int verbose ) } } - if (verbose != 0 ) + if( verbose != 0 ) printf( "passed\n" ); MPI_CHK( ecp_copy( &mul_tbl[0], &O ) ); @@ -507,9 +557,21 @@ int ecp_self_test( int verbose ) } } - if (verbose != 0 ) + if( verbose != 0 ) printf( "passed\n" ); + if( verbose != 0 ) + printf( " ECP test #3 (use_known_dp): " ); + + for( i = 0; i <= POLARSSL_ECP_DP_SECP521R1; i++ ) + { + MPI_CHK( ecp_use_known_dp( &grp, i ) ); + } + + if( verbose != 0 ) + printf( "passed\n" ); + + cleanup: if( ret != 0 && verbose != 0 ) From 4b8c3f2a1cbb9a9c5eb8535c8c437b23b6f3e17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 7 Nov 2012 21:39:45 +0100 Subject: [PATCH 16/76] Moved tests from selftest to tests/test_suite_ecp --- library/ecp.c | 180 +-------------------------- programs/test/selftest.c | 6 - tests/CMakeLists.txt | 1 + tests/suites/test_suite_ecp.data | 80 ++++++++++++ tests/suites/test_suite_ecp.function | 99 +++++++++++++++ 5 files changed, 181 insertions(+), 185 deletions(-) create mode 100644 tests/suites/test_suite_ecp.data create mode 100644 tests/suites/test_suite_ecp.function diff --git a/library/ecp.c b/library/ecp.c index ee3d6bfcc..13bdaa484 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -416,190 +416,12 @@ cleanup: #if defined(POLARSSL_SELF_TEST) -#include "polarssl/error.h" - -/* - * Return true iff P and Q are the same point - */ -static int ecp_point_eq( const ecp_point *P, const ecp_point *Q ) -{ - if( P->is_zero || Q->is_zero ) - return( P->is_zero && Q->is_zero ); - - return( mpi_cmp_mpi( &P->X, &Q->X ) == 0 && - mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 ); -} - -/* - * Print a point assuming its coordinates are small - */ -static void ecp_point_print( const ecp_point *P ) -{ - if( P->is_zero ) - printf( "zero\n" ); - else - printf( "(%lu, %lu)\n", P->X.p[0], P->Y.p[0] ); -} - -#define TEST_GROUP_ORDER 13 - /* * Checkup routine - * - * Data for basic tests with small values gathered from - * http://danher6.100webspace.net/ecc/#EFp_interactivo and double-checked - * using Pari-GP. */ int ecp_self_test( int verbose ) { - int ret = 0; - unsigned i; - ecp_group grp; - ecp_point O, A, B, C, D, E, F, G, H, TMP; - ecp_point *add_tbl[][3] = - { - { &O, &O, &O }, { &O, &A, &A }, { &A, &O, &A }, - { &A, &A, &O }, { &B, &C, &O }, { &C, &B, &O }, - { &A, &D, &E }, { &D, &A, &E }, - { &B, &D, &F }, { &D, &B, &F }, - { &D, &D, &G }, { &B, &B, &H }, - }; - mpi m; - ecp_point mul_tbl[TEST_GROUP_ORDER + 1]; - char *mul_tbl_s[TEST_GROUP_ORDER - 1][2] = - { - { "17", "42" }, - { "20", "01" }, - { "14", "11" }, - { "34", "33" }, - { "21", "32" }, - { "27", "30" }, - { "27", "17" }, - { "21", "15" }, - { "34", "14" }, - { "14", "36" }, - { "20", "46" }, - { "17", "05" }, - }; - - ecp_group_init( &grp ); - - ecp_point_init( &O ); ecp_point_init( &A ); ecp_point_init( &B ); - ecp_point_init( &C ); ecp_point_init( &D ); ecp_point_init( &E ); - ecp_point_init( &F ); ecp_point_init( &G ); ecp_point_init( &H ); - ecp_point_init( &TMP ); - - mpi_init( &m ); - - for( i = 0; i <= TEST_GROUP_ORDER; i++ ) - ecp_point_init( &mul_tbl[i] ); - - ecp_set_zero( &O ); - MPI_CHK( ecp_group_read_string( &grp, 10, "47", "4", "17", "42", "13" ) ); - MPI_CHK( ecp_point_read_string( &A, 10, "13", "00" ) ); - MPI_CHK( ecp_point_read_string( &B, 10, "14", "11" ) ); - MPI_CHK( ecp_point_read_string( &C, 10, "14", "36" ) ); - MPI_CHK( ecp_point_read_string( &D, 10, "37", "31" ) ); - MPI_CHK( ecp_point_read_string( &E, 10, "34", "14" ) ); - MPI_CHK( ecp_point_read_string( &F, 10, "45", "07" ) ); - MPI_CHK( ecp_point_read_string( &G, 10, "21", "32" ) ); - MPI_CHK( ecp_point_read_string( &H, 10, "27", "30" ) ); - - if( verbose != 0 ) - printf( " ECP test #1 (ecp_add): " ); - - for( i = 0; i < sizeof( add_tbl ) / sizeof( add_tbl[0] ); i++ ) - { - MPI_CHK( ecp_add( &grp, &TMP, add_tbl[i][0], add_tbl[i][1] ) ); - if( ! ecp_point_eq( &TMP, add_tbl[i][2] ) ) - { - if( verbose != 0 ) - { - printf( " failed (%u)\n", i ); - printf( " GOT: " ); - ecp_point_print( &TMP ); - printf( " EXPECTED: " ); - ecp_point_print( add_tbl[i][2] ); - } - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( ecp_copy( &mul_tbl[0], &O ) ); - for( i = 1; i <= TEST_GROUP_ORDER - 1; i++ ) - MPI_CHK( ecp_point_read_string( &mul_tbl[i], 10, - mul_tbl_s[i-1][0], mul_tbl_s[i-1][1] ) ); - MPI_CHK( ecp_copy( &mul_tbl[TEST_GROUP_ORDER], &O ) ); - - if( verbose != 0 ) - printf( " ECP test #2 (ecp_mul): " ); - - for( i = 0; i <= TEST_GROUP_ORDER; i++ ) - { - MPI_CHK( mpi_lset( &m, i ) ); - MPI_CHK( ecp_mul( &grp, &TMP, &m, &grp.G ) ); - if( ! ecp_point_eq( &TMP, &mul_tbl[i] ) ) - { - if( verbose != 0 ) - { - printf( " failed (%u)\n", i ); - printf( " GOT: " ); - ecp_point_print( &TMP ); - printf( " EXPECTED: " ); - ecp_point_print( &mul_tbl[i] ); - } - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - - if( verbose != 0 ) - printf( " ECP test #3 (use_known_dp): " ); - - for( i = 0; i <= POLARSSL_ECP_DP_SECP521R1; i++ ) - { - MPI_CHK( ecp_use_known_dp( &grp, i ) ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - -cleanup: - - if( ret != 0 && verbose != 0 ) - { -#if defined(POLARSSL_ERROR_C) - char error_buf[200]; - error_strerror( ret, error_buf, 200 ); - printf( "Unexpected error: %d - %s\n\n", ret, error_buf ); -#else - printf( "Unexpected error: %08X\n", ret ); -#endif - } - - ecp_group_free( &grp ); ecp_point_free( &O ); ecp_point_free( &TMP ); - - ecp_point_free( &A ); ecp_point_free( &B ); ecp_point_free( &C ); - ecp_point_free( &D ); ecp_point_free( &E ); ecp_point_free( &F ); - ecp_point_free( &G ); ecp_point_free( &H ); - - mpi_free( &m ); - - for( i = 0; i <= TEST_GROUP_ORDER; i++ ) - ecp_point_free( &mul_tbl[i] ); - - if( verbose != 0 ) - printf( "\n" ); - - return( ret ); + return( verbose++ ); } #endif diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 333e3a16d..8dddf3481 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -50,7 +50,6 @@ #include "polarssl/x509.h" #include "polarssl/xtea.h" #include "polarssl/pbkdf2.h" -#include "polarssl/ecp.h" int main( int argc, char *argv[] ) { @@ -156,11 +155,6 @@ int main( int argc, char *argv[] ) return( ret ); #endif -#if defined(POLARSSL_ECP_C) - if( ( ret = ecp_self_test( v ) ) != 0 ) - return( ret ); -#endif - #else printf( " POLARSSL_SELF_TEST not defined.\n" ); #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 18d5ad425..fda5bd36b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,6 +45,7 @@ add_test_suite(ctr_drbg) add_test_suite(debug) add_test_suite(des) add_test_suite(dhm) +add_test_suite(ecp) add_test_suite(error) add_test_suite(gcm gcm.encrypt) add_test_suite(gcm gcm.decrypt) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data new file mode 100644 index 000000000..85f163724 --- /dev/null +++ b/tests/suites/test_suite_ecp.data @@ -0,0 +1,80 @@ +ECP small addition #1 +ecp_small_add:1:"":"":1:"":"":1:0:0 + +ECP small addition #2 +ecp_small_add:1:"":"":0:"14":"11":0:14:11 + +ECP small addition #3 +ecp_small_add:0:"13":"00":0:"13":"00":1:0:0 + +ECP small addition #4 +ecp_small_add:0:"14":"11":0:"14":"36":1:0:0 + +ECP small addition #5 +ecp_small_add:0:"13":"00":0:"37":"31":0:34:14 + +ECP small addition #6 +ecp_small_add:0:"14":"11":0:"37":"31":0:45:07 + +ECP small addition #7 +ecp_small_add:0:"37":"31":0:"37":"31":0:21:32 + +ECP small addition #8 +ecp_small_add:0:"14":"11":0:"14":"11":0:27:30 + +ECP small multiplication #0 +ecp_small_mul:0:1:0:0 + +ECP small multiplication #1 +ecp_small_mul:1:0:17:42 + +ECP small multiplication #2 +ecp_small_mul:2:0:20:01 + +ECP small multiplication #3 +ecp_small_mul:3:0:14:11 + +ECP small multiplication #4 +ecp_small_mul:4:0:34:33 + +ECP small multiplication #5 +ecp_small_mul:5:0:21:32 + +ECP small multiplication #6 +ecp_small_mul:6:0:27:30 + +ECP small multiplication #7 +ecp_small_mul:7:0:27:17 + +ECP small multiplication #8 +ecp_small_mul:8:0:21:15 + +ECP small multiplication #9 +ecp_small_mul:9:0:34:14 + +ECP small multiplication #10 +ecp_small_mul:10:0:14:36 + +ECP small multiplication #11 +ecp_small_mul:11:0:20:46 + +ECP small multiplication #12 +ecp_small_mul:12:0:17:05 + +ECP small multiplication #13 +ecp_small_mul:13:1:0:0 + +ECP test vectors secp192r1 +ecp_test_vect:SECP192R1 + +ECP test vectors secp224r1 +ecp_test_vect:SECP224R1 + +ECP test vectors secp256r1 +ecp_test_vect:SECP256R1 + +ECP test vectors secp384r1 +ecp_test_vect:SECP384R1 + +ECP test vectors secp521r1 +ecp_test_vect:SECP521R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function new file mode 100644 index 000000000..442761328 --- /dev/null +++ b/tests/suites/test_suite_ecp.function @@ -0,0 +1,99 @@ +BEGIN_HEADER +#include +END_HEADER + +BEGIN_DEPENDENCIES +depends_on:POLARSSL_ECP_C:POLARSSL_BIGNUM_C +END_DEPENDENCIES + +BEGIN_CASE +ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c +{ + ecp_group grp; + ecp_point A, B, C; + + ecp_group_init( &grp ); + ecp_point_init( &A ); ecp_point_init( &B ); ecp_point_init( &C ); + + TEST_ASSERT( ecp_group_read_string( &grp, 10, + "47", "4", "17", "42", "13" ) == 0 ); + + if( {a_zero} ) + ecp_set_zero( &A ); + else + TEST_ASSERT( ecp_point_read_string( &A, 10, {x_a}, {y_a} ) == 0 ); + + if( {b_zero} ) + ecp_set_zero( &B ); + else + TEST_ASSERT( ecp_point_read_string( &B, 10, {x_b}, {y_b} ) == 0 ); + + TEST_ASSERT( ecp_add( &grp, &C, &A, &B ) == 0 ); + + if( {c_zero} ) + TEST_ASSERT( C.is_zero ); + else + { + TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 ); + TEST_ASSERT( mpi_cmp_int( &C.Y, {y_c} ) == 0 ); + } + + TEST_ASSERT( ecp_add( &grp, &C, &B, &A ) == 0 ); + + if( {c_zero} ) + TEST_ASSERT( C.is_zero ); + else + { + TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 ); + TEST_ASSERT( mpi_cmp_int( &C.Y, {y_c} ) == 0 ); + } + + ecp_group_free( &grp ); + ecp_point_free( &A ); ecp_point_free( &B ); ecp_point_free( &C ); +} +END_CASE + +BEGIN_CASE +ecp_small_mul:m:r_zero:x_r:y_r +{ + ecp_group grp; + ecp_point R; + mpi m; + + ecp_group_init( &grp ); + ecp_point_init( &R ); + mpi_init( &m ); + + TEST_ASSERT( ecp_group_read_string( &grp, 10, + "47", "4", "17", "42", "13" ) == 0 ); + + TEST_ASSERT( mpi_lset( &m, {m} ) == 0 ); + + TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == 0 ); + + if( {r_zero} ) + TEST_ASSERT( R.is_zero ); + else + { + TEST_ASSERT( mpi_cmp_int( &R.X, {x_r} ) == 0 ); + TEST_ASSERT( mpi_cmp_int( &R.Y, {y_r} ) == 0 ); + } + + ecp_group_free( &grp ); + ecp_point_free( &R ); + mpi_free( &m ); +} +END_CASE + +BEGIN_CASE +ecp_test_vect:id +{ + ecp_group grp; + + ecp_group_init( &grp ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + ecp_group_free( &grp ); +} +END_CASE From e739f0133b3225dfd05b9217e2bfe5ca33372a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 7 Nov 2012 12:24:22 +0100 Subject: [PATCH 17/76] Added test vectors from RFC 5114 to test suite --- tests/suites/test_suite_ecp.data | 10 ++++---- tests/suites/test_suite_ecp.function | 35 +++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 85f163724..41d3145f0 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -65,16 +65,16 @@ ECP small multiplication #13 ecp_small_mul:13:1:0:0 ECP test vectors secp192r1 -ecp_test_vect:SECP192R1 +ecp_test_vect:SECP192R1:"323FA3169D8E9C6593F59476BC142000AB5BE0E249C43426":"CD46489ECFD6C105E7B3D32566E2B122E249ABAADD870612":"68887B4877DF51DD4DC3D6FD11F0A26F8FD3844317916E9A":"631F95BB4A67632C9C476EEE9AB695AB240A0499307FCF62":"519A121680E0045466BA21DF2EEE47F5973B500577EF13D5":"FF613AB4D64CEE3A20875BDB10F953F6B30CA072C60AA57F":"AD420182633F8526BFE954ACDA376F05E5FF4F837F54FEBE":"4371545ED772A59741D0EDA32C671112B7FDDD51461FCF32" ECP test vectors secp224r1 -ecp_test_vect:SECP224R1 +ecp_test_vect:SECP224R1:"B558EB6C288DA707BBB4F8FBAE2AB9E9CB62E3BC5C7573E22E26D37F":"49DFEF309F81488C304CFF5AB3EE5A2154367DC7833150E0A51F3EEB":"4F2B5EE45762C4F654C1A0C67F54CF88B016B51BCE3D7C228D57ADB4":"AC3B1ADD3D9770E6F6A708EE9F3B8E0AB3B480E9F27F85C88B5E6D18":"6B3AC96A8D0CDE6A5599BE8032EDF10C162D0A8AD219506DCD42A207":"D491BE99C213A7D1CA3706DEBFE305F361AFCBB33E2609C8B1618AD5":"52272F50F46F4EDC9151569092F46DF2D96ECC3B6DC1714A4EA949FA":"5F30C6AA36DDC403C0ACB712BB88F1763C3046F6D919BD9C524322BF" ECP test vectors secp256r1 -ecp_test_vect:SECP256R1 +ecp_test_vect:SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"B120DE4AA36492795346E8DE6C2C8646AE06AAEA279FA775B3AB0715F6CE51B0":"9F1B7EECE20D7B5ED8EC685FA3F071D83727027092A8411385C34DDE5708B2B6":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50" ECP test vectors secp384r1 -ecp_test_vect:SECP384R1 +ecp_test_vect:SECP384R1:"D27335EA71664AF244DD14E9FD1260715DFD8A7965571C48D709EE7A7962A156D706A90CBCB5DF2986F05FEADB9376F1":"793148F1787634D5DA4C6D9074417D05E057AB62F82054D10EE6B0403D6279547E6A8EA9D1FD77427D016FE27A8B8C66":"C6C41294331D23E6F480F4FB4CD40504C947392E94F4C3F06B8F398BB29E42368F7A685923DE3B67BACED214A1A1D128":"52D1791FDB4B70F89C0F00D456C2F7023B6125262C36A7DF1F80231121CCE3D39BE52E00C194A4132C4A6C768BCD94D2":"5CD42AB9C41B5347F74B8D4EFB708B3D5B36DB65915359B44ABC17647B6B9999789D72A84865AE2F223F12B5A1ABC120":"E171458FEAA939AAA3A8BFAC46B404BD8F6D5B348C0FA4D80CECA16356CA933240BDE8723415A8ECE035B0EDF36755DE":"5EA1FC4AF7256D2055981B110575E0A8CAE53160137D904C59D926EB1B8456E427AA8A4540884C37DE159A58028ABC0E":"0CC59E4B046414A81C8A3BDFDCA92526C48769DD8D3127CAA99B3632D1913942DE362EAFAA962379374D9F3F066841CA" ECP test vectors secp521r1 -ecp_test_vect:SECP521R1 +ecp_test_vect:SECP521R1:"0113F82DA825735E3D97276683B2B74277BAD27335EA71664AF2430CC4F33459B9669EE78B3FFB9B8683015D344DCBFEF6FB9AF4C6C470BE254516CD3C1A1FB47362":"01EBB34DD75721ABF8ADC9DBED17889CBB9765D90A7C60F2CEF007BB0F2B26E14881FD4442E689D61CB2DD046EE30E3FFD20F9A45BBDF6413D583A2DBF59924FD35C":"00F6B632D194C0388E22D8437E558C552AE195ADFD153F92D74908351B2F8C4EDA94EDB0916D1B53C020B5EECAED1A5FC38A233E4830587BB2EE3489B3B42A5A86A4":"00CEE3480D8645A17D249F2776D28BAE616952D1791FDB4B70F7C3378732AA1B22928448BCD1DC2496D435B01048066EBE4F72903C361B1A9DC1193DC2C9D0891B96":"010EBFAFC6E85E08D24BFFFCC1A4511DB0E634BEEB1B6DEC8C5939AE44766201AF6200430BA97C8AC6A0E9F08B33CE7E9FEEB5BA4EE5E0D81510C24295B8A08D0235":"00A4A6EC300DF9E257B0372B5E7ABFEF093436719A77887EBB0B18CF8099B9F4212B6E30A1419C18E029D36863CC9D448F4DBA4D2A0E60711BE572915FBD4FEF2695":"00CDEA89621CFA46B132F9E4CFE2261CDE2D4368EB5656634C7CC98C7A00CDE54ED1866A0DD3E6126C9D2F845DAFF82CEB1DA08F5D87521BB0EBECA77911169C20CC":"00F9A71641029B7FC1A808AD07CD4861E868614B865AFBECAB1F2BD4D8B55EBCB5E3A53143CEB2C511B1AE0AF5AC827F60F2FD872565AC5CA0A164038FE980A7E4BD" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 442761328..d81ff881e 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -86,14 +86,43 @@ ecp_small_mul:m:r_zero:x_r:y_r END_CASE BEGIN_CASE -ecp_test_vect:id +ecp_test_vect:id:dA:xA:yA:dB:xB:yB:xZ:yZ { ecp_group grp; + ecp_point R; + mpi dA, xA, yA, dB, xB, yB, xZ, yZ; - ecp_group_init( &grp ); + ecp_group_init( &grp ); ecp_point_init( &R ); + mpi_init( &dA ); mpi_init( &xA ); mpi_init( &yA ); mpi_init( &dB ); + mpi_init( &xB ); mpi_init( &yB ); mpi_init( &xZ ); mpi_init( &yZ ); TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); - ecp_group_free( &grp ); + TEST_ASSERT( mpi_read_string( &dA, 16, {dA} ) == 0 ); + TEST_ASSERT( mpi_read_string( &xA, 16, {xA} ) == 0 ); + TEST_ASSERT( mpi_read_string( &yA, 16, {yA} ) == 0 ); + TEST_ASSERT( mpi_read_string( &dB, 16, {dB} ) == 0 ); + TEST_ASSERT( mpi_read_string( &xB, 16, {xB} ) == 0 ); + TEST_ASSERT( mpi_read_string( &yB, 16, {yB} ) == 0 ); + TEST_ASSERT( mpi_read_string( &xZ, 16, {xZ} ) == 0 ); + TEST_ASSERT( mpi_read_string( &yZ, 16, {yZ} ) == 0 ); + + TEST_ASSERT( ecp_mul( &grp, &R, &dA, &grp.G ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.X, &xA ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yA ) == 0 ); + TEST_ASSERT( ecp_mul( &grp, &R, &dB, &R ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 ); + + TEST_ASSERT( ecp_mul( &grp, &R, &dB, &grp.G ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.X, &xB ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yB ) == 0 ); + TEST_ASSERT( ecp_mul( &grp, &R, &dA, &R ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 ); + + ecp_group_free( &grp ); ecp_point_free( &R ); + mpi_free( &dA ); mpi_free( &xA ); mpi_free( &yA ); mpi_free( &dB ); + mpi_free( &xB ); mpi_free( &yB ); mpi_free( &xZ ); mpi_free( &yZ ); } END_CASE From e870c0a5d630ab327aabdb87991aec5f71ccee85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 11:31:48 +0100 Subject: [PATCH 18/76] Added benchmark for DHM --- programs/test/benchmark.c | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c index 86de2c63c..7ee465f4d 100644 --- a/programs/test/benchmark.c +++ b/programs/test/benchmark.c @@ -45,6 +45,7 @@ #include "polarssl/camellia.h" #include "polarssl/gcm.h" #include "polarssl/rsa.h" +#include "polarssl/dhm.h" #include "polarssl/timing.h" #include "polarssl/havege.h" #include "polarssl/ctr_drbg.h" @@ -120,6 +121,10 @@ int main( int argc, char *argv[] ) #endif #if defined(POLARSSL_CTR_DRBG_C) ctr_drbg_context ctr_drbg; +#endif +#if defined(POLARSSL_DHM_C) && defined(POLARSSL_BIGNUM_C) + dhm_context dhm; + size_t olen = BUFSIZE; #endif ((void) argc); ((void) argv); @@ -505,6 +510,74 @@ int main( int argc, char *argv[] ) rsa_free( &rsa ); #endif +#if defined(POLARSSL_DHM_C) && defined(POLARSSL_BIGNUM_C) + memset( &dhm, 0, sizeof( dhm_context ) ); + + mpi_read_string( &dhm.P, 16, POLARSSL_DHM_RFC5114_MODP_1024_P ); + mpi_read_string( &dhm.G, 16, POLARSSL_DHM_RFC5114_MODP_1024_G ); + dhm.len = mpi_size( &dhm.P ); + dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL ); + mpi_copy( &dhm.GY, &dhm.GX ); + + printf( HEADER_FORMAT, "DHM-1024" ); + fflush( stdout ); + set_alarm( 3 ); + + for( i = 1; ! alarmed; i++ ) + { + dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL ); + dhm_calc_secret( &dhm, buf, &olen ); + } + + printf( "%9lu handshake/s\n", i / 3 ); + + dhm_free( &dhm ); + + memset( &dhm, 0, sizeof( dhm_context ) ); + + mpi_read_string( &dhm.P, 16, POLARSSL_DHM_RFC3526_MODP_2048_P ); + mpi_read_string( &dhm.G, 16, POLARSSL_DHM_RFC3526_MODP_2048_G ); + dhm.len = mpi_size( &dhm.P ); + dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL ); + mpi_copy( &dhm.GY, &dhm.GX ); + + printf( HEADER_FORMAT, "DHM-2048" ); + fflush( stdout ); + set_alarm( 3 ); + + for( i = 1; ! alarmed; i++ ) + { + dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL ); + dhm_calc_secret( &dhm, buf, &olen ); + } + + printf( "%9lu handshake/s\n", i / 3 ); + + dhm_free( &dhm ); + + memset( &dhm, 0, sizeof( dhm_context ) ); + + mpi_read_string( &dhm.P, 16, POLARSSL_DHM_RFC3526_MODP_3072_P ); + mpi_read_string( &dhm.G, 16, POLARSSL_DHM_RFC3526_MODP_3072_G ); + dhm.len = mpi_size( &dhm.P ); + dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL ); + mpi_copy( &dhm.GY, &dhm.GX ); + + printf( HEADER_FORMAT, "DHM-3072" ); + fflush( stdout ); + set_alarm( 3 ); + + for( i = 1; ! alarmed; i++ ) + { + dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL ); + dhm_calc_secret( &dhm, buf, &olen ); + } + + printf( "%9lu handshake/s\n", i / 3 ); + + dhm_free( &dhm ); +#endif + printf( "\n" ); #if defined(_WIN32) From 52a422f6a10519d2999ece44ede0d09da8793e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 14:56:25 +0100 Subject: [PATCH 19/76] Added ecp-bench specialized benchmark --- programs/.gitignore | 1 + programs/test/CMakeLists.txt | 3 + programs/test/ecp-bench.c | 205 +++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 programs/test/ecp-bench.c diff --git a/programs/.gitignore b/programs/.gitignore index d6d9efcf6..9a6953247 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -29,6 +29,7 @@ ssl/ssl_mail_client ssl/ssl_server ssl/ssl_server2 test/benchmark +test/ecp-bench test/o_p_test test/selftest test/ssl_cert_test diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt index c05b903f4..56bcae082 100644 --- a/programs/test/CMakeLists.txt +++ b/programs/test/CMakeLists.txt @@ -18,6 +18,9 @@ target_link_libraries(selftest ${libs}) add_executable(benchmark benchmark.c) target_link_libraries(benchmark ${libs}) +add_executable(ecp-bench ecp-bench.c) +target_link_libraries(ecp-bench ${libs}) + add_executable(ssl_test ssl_test.c) target_link_libraries(ssl_test ${libs}) diff --git a/programs/test/ecp-bench.c b/programs/test/ecp-bench.c new file mode 100644 index 000000000..3064cc9eb --- /dev/null +++ b/programs/test/ecp-bench.c @@ -0,0 +1,205 @@ +/* + * Temporary mini-benchmark for ECP multiplication + * (and comparision with GF(p) exponentation if any argument is given) + */ + +#include +#include +#include + +#include "polarssl/config.h" + +#include "polarssl/dhm.h" +#include "polarssl/ecp.h" +#include "polarssl/timing.h" +#include "polarssl/error.h" + +#if !defined(POLARSSL_TIMING_C) || !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_DHM_C) || !defined(POLARSSL_ECP_C) + +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_{TIMING,BIGNUM,DHM,ECP}_C not defined.\n"); + return( 0 ); +} + +#else + +void dhm_bench_case( const char *s, const char *p, + const char *g, const char *x ) +{ + unsigned long i; + mpi P, G, X, R, C; + + mpi_init( &P ); mpi_init( &G ); mpi_init( &X ); mpi_init( &R ); + mpi_init( &C ); + + mpi_read_string( &P, 16, p ); + mpi_read_string( &G, 16, g ); + mpi_read_string( &X, 16, x ); + + printf( " MODP-%s : ", s ); + fflush( stdout ); + set_alarm( 3 ); + + for( i = 1; ! alarmed; i++ ) + mpi_exp_mod( &R, &G, &X, &P, &C ); + + printf( "%9lu exp/s\n", i / 3 ); + + mpi_free( &P ); mpi_free( &G ); mpi_free( &X ); mpi_free( &R ); + mpi_free( &C ); +} + +#define MODP_1024_G \ + "205BE4D89282CE6A9488626CA9BCC1264E7C9525903F049D" \ + "D6A77315AA12B01467EB1EA21B25569BECEC276623859A8C" \ + "518D445DF43DCBA1B75D23B6BB6B96084FA3C10CA8DC1A96" \ + "77E26332152233E13F4E6BF3C5D48514BC264A35AF385463" \ + "8B8AE5E363BD6AE0B5D44875BB60A73A5E4075FB2037B833" \ + "DC382EA6DD458EAE" + +#define MODP_1024_X \ + "262F6727B2E44AF61981AAAB2AA749F64FD79AD18A1FC999" \ + "2E71795130CB69F89BCFB70DB2A0F2A49A825A0AAA50715D" \ + "5D9AE98198F0522AECBF8A0A2D331AB0296110617FC685FF" \ + "7338F4201329ABDFDEAEC779E4D56CC46A0A38B18DC18DFE" \ + "640865426A7360BCCD4E4F82B3686B4804071D4B9F5582ED" \ + "E4758F170C3A1415" + +#define MODP_2048_G \ + "717892E6698EB3CD62113AAE793EA6690791F89290FD83C3" \ + "A059F328C5FBD10AB25C1E8F96245836600FC7772AFB42ED" \ + "F7A809FC3D38F7794574CAC8A318D41C917EE34C81EA8838" \ + "BA6068E81ED3C7F039A83914D044AB2379B3C5C24F0FFD4E" \ + "B6642F26F1EDF015AB7829E9EDC8DCD8A4013C76682338E8" \ + "3D44B0F4E870CF3134874EAA3AC0803DA2CE30922E251B02" \ + "BDDD94137F9DFD41627AE20B7E4137BA94496A4B2AEB0354" \ + "8E1C4126A87240B43E23BB574D354EF1AD01FED5627F240C" \ + "2F4F5521D2F51DFE0702D18EED6DDF022D93554E7AB67D81" \ + "AD4C5256A6AC00DE1AD0751FDCC17F8C7136C194F48A39F5" \ + "957B831081C9058CA0C3A03C7C41F1C9" + +#define MODP_2048_X \ + "AFA7186FC7A0370DE6E3DD95473C9D10C916BD186E41FB48" \ + "195D123E5CFE8D237A2A640DCE19B3DD7028C6168084A61D" \ + "4E4E218A1D98E0C2C93E2E1516F97E596B50C811CE93417B" \ + "905DA6833D1CE41838AEAA9CA6CE36E2430A244A6696E99B" \ + "54B6AAC75D4F6FF6F0568145BDBBC83F5F603D698198A8EE" \ + "2098F5DCABDD458C465E795520EDD46C3B992EAFACF24A56" \ + "263850C9A07165A0CE52B7DC71489CA67AC4A6E6176B547B" \ + "A1C233E3C7898C283E82B3E74B9056F84F7B4A10B5CE10FF" \ + "7D43107B68F2381E64C77C61474DE8CA70EA8DF935D43CD2" \ + "CE208D9F7E468F07A93A74676ED1A3C77CB1CD59E96DCA77" \ + "125DE5B672798FC943048FDBB24167B1" + +#define MODP_3072_G \ + "38B2B12253661411B63E62F3FAC5BE7CF6A416F249E4A039" \ + "0884765C18F2EDF93FCC2646B888ED64B783765D576887B1" \ + "74ABB76123ECA6537DDC1F95757645F3C870CBFF2D40E40D" \ + "C2556A14115C37BE299BDCB0F07AB7AAE0D8FA6CF44A0C22" \ + "ED5368922EF028EC2B5B0AB42F858D5D780828A508C252A7" \ + "96F8CE7AA9C83D1E820F6991771AAA2286A7754FCCB3AA16" \ + "51D840EC788C5DDEAFAAC0C82EAC84EBFF5EB52699BE4020" \ + "F62607937EB168766BCC1F786F4FCDDBB66C0BCEA983AE87" \ + "5C2DD6C201FBF5C178308E64831D14F12399F21761D13BC1" \ + "20B2377FBAD73613FA7B7E443BEE3879E7EEFB0A625A0EBA" \ + "2D379E8F5EA62C91BC58A6FCDD5D7435B0E747B7B65A47BE" \ + "0CA769DE340E611A98A6DDED72E89486875F02DAE24715E8" \ + "3787A5DB53AA28D3F838E7F11EE80F0310C8597B585D6B1A" \ + "3991FBD7459ED277C34C9A4AE0AE6DC7EE5C99B14F366129" \ + "C3747617B724A2BED48F5BF3106B40E60CC3677780F1A39D" \ + "430154C2B460CC676AACC7B34F792621D743D1AC59EDBAC6" + +#define MODP_3072_X \ + "4391157AD824806F07421C1545AA795E26B120A5CEE427F0" \ + "6725BB247E6B2F4C4BE052E4B240B2DD6194B37F3423FA3F" \ + "00C3DF9F4C2165662FCCC9B8DE52C19001E8D54E9053A605" \ + "24BCA6AB0698632EB5D62451987E89AF0FA63479D344E2A7" \ + "58ED8DB5D287600C85A8DD08D9E2E5587177AB6A25A76C71" \ + "5BCAA737FB7DC45E371F4DEC13B40CA9D461A99A98847E1B" \ + "D9CD1BA02DCC331B5B2256887B7F0139A9E7BEA8A6CDA318" \ + "B95E12A1CEE6A26EC070C34C270067C79DBC906295C3C9DF" \ + "2FA6D6B637B7CE81B535DB2D6E196F46ED2F92F3EE8EACE1" \ + "002349D035550A44B75E76B7A77A6A670EC13E334201B543" \ + "B1708295F33B777BD4555A032313C3388DBD5ABC5FB0FEFD" \ + "A9A98C0CC4C7E919927BDC8D46B5347A1266A4C8331C2EB0" \ + "C93DB67244BD6CE2757BA61A063DDD0DF0561A97786D1299" \ + "EBE3EAC838F420D1A0DC9D633B2F16CCE91E436C0413CE6A" \ + "F98E0273FC5C08A4EA70D6DC09A1855AFB402E02BD9F261E" \ + "863717A552F4A83D4DD5060CB70E2D4D7FFAEE912C2C4408" + +void dhm_bench( void ) +{ + dhm_bench_case( "1024", POLARSSL_DHM_RFC5114_MODP_1024_P, + MODP_1024_G, MODP_1024_X ); + + dhm_bench_case( "2048", POLARSSL_DHM_RFC3526_MODP_2048_P, + MODP_2048_G, MODP_2048_X ); + + dhm_bench_case( "3072", POLARSSL_DHM_RFC3526_MODP_3072_P, + MODP_3072_G, MODP_3072_X ); +} + +void ecp_bench_case( size_t dp, char *s, char *m ) +{ + unsigned long i; + ecp_group grp; + ecp_point R; + mpi M; + + ecp_group_init( &grp ); ecp_point_init( &R ); mpi_init( &M ); + + ecp_use_known_dp( &grp, dp ); + mpi_read_string( &M, 16, m ); + + printf( " ECP-%s : ", s ); + fflush( stdout ); + set_alarm( 3 ); + + for( i = 1; ! alarmed; i++ ) + ecp_mul( &grp, &R, &M, &grp.G ); + + printf( "%9lu mul/s\n", i / 3 ); + + ecp_group_free( &grp ); ecp_point_free( &R ); mpi_free( &M ); +} + +#define ECP_192_M \ + "FE61330B02915F25970C2AF8575CBB227E6B6394774E6EC8" +#define ECP_224_M \ + "EAC63628087E32F61A383DCAED57E4348081FF3637D95B904C2FD487" +#define ECP_256_M \ + "83C4106612BDDB781DD446CF2A873D78AA0620B9003789244A18F83B39B3EA63" +#define ECP_384_M \ + "3E45569675A7E2E0E2E663A11E4226FBEF0F99A96CD6E547" \ + "9ABDDF36DD9AB7278BCD8B96A0775847A6431D2AF7476CD9" +#define ECP_521_M \ + "017F540D09F24EC6B102E8E4A9F14B850442D98C68FB29A6B09B9B9D40E2A750" \ + "7F3D2D6C5B6536B607EF2BCEA4797BB3A68F0D745410EB5CFFC7FF7FB17381544E" + +void ecp_bench( void ) +{ + ecp_bench_case( 0, "192", ECP_192_M ); + ecp_bench_case( 1, "224", ECP_224_M ); + ecp_bench_case( 2, "256", ECP_256_M ); + ecp_bench_case( 3, "384", ECP_384_M ); + ecp_bench_case( 4, "521", ECP_521_M ); +} + +int main( int argc, char *argv[] ) +{ + ((void) argv); + if( argc > 1 ) + { + dhm_bench(); + } + + ecp_bench(); + + return( 0 ); +} +#endif From d070f5122425679d9b327eb05390b06b1658d018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 17:40:51 +0100 Subject: [PATCH 20/76] Started introducting Jacobian coordinates --- library/ecp.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/library/ecp.c b/library/ecp.c index 13bdaa484..6812718a5 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -27,7 +27,7 @@ * References: * * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - * Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone */ #include "polarssl/config.h" @@ -206,6 +206,80 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) return( POLARSSL_ERR_ECP_GENERIC ); } +/* + * Internal point format used for fast addition/doubling/multiplication: + * Jacobian coordinates (GECC example 3.20) + */ +typedef struct +{ + mpi X, Y, Z; +} +ecp_ptjac; + +/* + * Convert from affine to Jacobian coordinates + */ +static int ecp_aff_to_jac( ecp_ptjac *jac, ecp_point *aff ) +{ + int ret = 0; + + if( aff->is_zero ) + { + MPI_CHK( mpi_lset( &jac->X, 1 ) ); + MPI_CHK( mpi_lset( &jac->Y, 1 ) ); + MPI_CHK( mpi_lset( &jac->Z, 0 ) ); + } + else + { + MPI_CHK( mpi_copy( &jac->X, &aff->X ) ); + MPI_CHK( mpi_copy( &jac->Y, &aff->Y ) ); + MPI_CHK( mpi_lset( &jac->Z, 1 ) ); + } + +cleanup: + return( ret ); +} + +/* + * Convert from Jacobian to affine coordinates + */ +static int ecp_jac_to_aff( const ecp_group *grp, + ecp_point *aff, ecp_ptjac *jac ) +{ + int ret = 0; + mpi Zi, ZZi, T; + + if( mpi_cmp_int( &jac->Z, 0 ) == 0 ) { + ecp_set_zero( aff ); + return( 0 ); + } + + mpi_init( &Zi ); mpi_init( &ZZi ); mpi_init( &T ); + + aff->is_zero = 0; + + /* + * aff.X = jac.X / (jac.Z)^2 mod p + */ + MPI_CHK( mpi_inv_mod( &Zi, &jac->Z, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); + MPI_CHK( mpi_mul_mpi( &T, &jac->X, &ZZi ) ); + MPI_CHK( mpi_mod_mpi( &aff->X, &T, &grp->P ) ); + + /* + * aff.Y = jac.Y / (jac.Z)^3 mod p + */ + MPI_CHK( mpi_mul_mpi( &T, &jac->Y, &ZZi ) ); + MPI_CHK( mpi_mul_mpi( &T, &T, &Zi ) ); + MPI_CHK( mpi_mod_mpi( &aff->Y, &T, &grp->P ) ); + +cleanup: + + mpi_free( &Zi ); mpi_free( &ZZi ); mpi_free( &T ); + + return( ret ); +} + /* * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) * Cf SEC1 v2 p. 7, item 4 From 27b1ba8be02e6921bba9f2333df0a69e5dfc8897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 18:24:10 +0100 Subject: [PATCH 21/76] Changed ecp_mul() to always add the same point --- library/ecp.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 6812718a5..503f9d8d2 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -434,55 +434,42 @@ int ecp_add( const ecp_group *grp, ecp_point *R, /* * Integer multiplication: R = m * P - * Using Montgomery's Ladder to avoid leaking information about m + * GECC 5.7 (SPA-resistant algorithm) */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ) { int ret = 0; size_t pos; - ecp_point A, B; + ecp_point Q[2]; - ecp_point_init( &A ); ecp_point_init( &B ); + ecp_point_init( &Q[0] ); ecp_point_init( &Q[1] ); /* - * The general method works only for m >= 2 + * The general method works only for m >= 1 */ if( mpi_cmp_int( m, 0 ) == 0 ) { ecp_set_zero( R ); goto cleanup; } - if( mpi_cmp_int( m, 1 ) == 0 ) { - MPI_CHK( ecp_copy( R, P ) ); - goto cleanup; - } + ecp_set_zero( &Q[0] ); - MPI_CHK( ecp_copy( &A, P ) ); - MPI_CHK( ecp_add( grp, &B, P, P ) ); - - for( pos = mpi_msb( m ) - 2; ; pos-- ) + for( pos = mpi_msb( m ) - 1; ; pos-- ) { - if( mpi_get_bit( m, pos ) == 0 ) - { - MPI_CHK( ecp_add( grp, &B, &A, &B ) ); - MPI_CHK( ecp_add( grp, &A, &A, &A ) ) ; - } - else - { - MPI_CHK( ecp_add( grp, &A, &A, &B ) ); - MPI_CHK( ecp_add( grp, &B, &B, &B ) ) ; - } + MPI_CHK( ecp_add( grp, &Q[0], &Q[0], &Q[0] ) ); + MPI_CHK( ecp_add( grp, &Q[1], &Q[0], P ) ); + MPI_CHK( ecp_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); if( pos == 0 ) break; } - MPI_CHK( ecp_copy( R, &A ) ); + MPI_CHK( ecp_copy( R, &Q[0] ) ); cleanup: - ecp_point_free( &A ); ecp_point_free( &B ); + ecp_point_free( &Q[0] ); ecp_point_free( &Q[1] ); return( ret ); } From 989c32bc3e92a473192e816e1a871a89d913a9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 22:02:42 +0100 Subject: [PATCH 22/76] Replaced double_generic with double_jac --- library/ecp.c | 151 +++++++++++++++++++++++++++----------------------- 1 file changed, 83 insertions(+), 68 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 503f9d8d2..3541f0b8e 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -216,10 +216,26 @@ typedef struct } ecp_ptjac; +/* + * Initialize a point in Jacobian coordinates + */ +static void ecp_ptjac_init( ecp_ptjac *P ) +{ + mpi_init( &P->X ); mpi_init( &P->Y ); mpi_init( &P->Z ); +} + +/* + * Free a point in Jacobian cooridnates + */ +static void ecp_ptjac_free( ecp_ptjac *P ) +{ + mpi_free( &P->X ); mpi_free( &P->Y ); mpi_free( &P->Z ); +} + /* * Convert from affine to Jacobian coordinates */ -static int ecp_aff_to_jac( ecp_ptjac *jac, ecp_point *aff ) +static int ecp_aff_to_jac( ecp_ptjac *jac, const ecp_point *aff ) { int ret = 0; @@ -244,7 +260,7 @@ cleanup: * Convert from Jacobian to affine coordinates */ static int ecp_jac_to_aff( const ecp_group *grp, - ecp_point *aff, ecp_ptjac *jac ) + ecp_point *aff, const ecp_ptjac *jac ) { int ret = 0; mpi Zi, ZZi, T; @@ -280,6 +296,58 @@ cleanup: return( ret ); } +/* + * Point doubling R = 2 P, Jacobian coordinates (GECC 3.21) + */ +static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, + const ecp_ptjac *P ) +{ + int ret = 0; + mpi T1, T2, T3, X, Y, Z; + + mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + MPI_CHK( mpi_lset( &R->X, 1 ) ); + MPI_CHK( mpi_lset( &R->Y, 1 ) ); + MPI_CHK( mpi_lset( &R->Z, 0 ) ); + goto cleanup; + } + + MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); + MPI_CHK( mpi_sub_mpi( &T2, &P->X, &T1 ) ); + MPI_CHK( mpi_add_mpi( &T1, &P->X, &T1 ) ); + MPI_CHK( mpi_mul_mpi( &T2, &T2, &T1 ) ); + MPI_CHK( mpi_mul_int( &T2, &T2, 3 ) ); + MPI_CHK( mpi_copy ( &Y, &P->Y ) ); + MPI_CHK( mpi_shift_l( &Y, 1 ) ); + MPI_CHK( mpi_mul_mpi( &Z, &Y, &P->Z ) ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); + MPI_CHK( mpi_mul_mpi( &T3, &Y, &P->X ) ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); + MPI_CHK( mpi_copy ( &T1, &T3 ) ); + MPI_CHK( mpi_shift_l( &T1, 1 ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + MPI_CHK( mpi_sub_mpi( &T1, &T3, &X ) ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &T2 ) ); + MPI_CHK( mpi_sub_mpi( &Y, &T1, &Y ) ); + + MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) ); + MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); + MPI_CHK( mpi_mod_mpi( &R->Z, &Z, &grp->P ) ); + +cleanup: + + mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 ); + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + + return( ret ); +} + /* * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) * Cf SEC1 v2 p. 7, item 4 @@ -336,66 +404,6 @@ cleanup: return( ret ); } -/* - * Doubling: R = 2 * P, generic case (P != 0, R != 0) - * Cf SEC1 v2 p. 7, item 5 - */ -static int ecp_double_generic( const ecp_group *grp, ecp_point *R, - const ecp_point *P ) -{ - int ret = 0; - mpi LN, LD, K, L, LL, X, Y; - - mpi_init( &LN ); mpi_init( &LD ); mpi_init( &K ); mpi_init( &L ); - mpi_init( &LL ); mpi_init( &X ); mpi_init( &Y ); - - /* - * L = 3 (P.X - 1) (P.X + 1) / (2 P.Y) mod p - */ - MPI_CHK( mpi_copy( &LD, &P->Y ) ); - MPI_CHK( mpi_shift_l( &LD, 1 ) ); - MPI_CHK( mpi_inv_mod( &K, &LD, &grp->P ) ); - MPI_CHK( mpi_mul_int( &K, &K, 3 ) ); - MPI_CHK( mpi_sub_int( &LN, &P->X, 1 ) ); - MPI_CHK( mpi_mul_mpi( &K, &K, &LN ) ); - MPI_CHK( mpi_add_int( &LN, &P->X, 1 ) ); - MPI_CHK( mpi_mul_mpi( &K, &K, &LN ) ); - MPI_CHK( mpi_mod_mpi( &L, &K, &grp->P ) ); - - /* - * LL = L^2 mod p - */ - MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) ); - MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) ); - - /* - * X = L^2 - 2 * P.X - */ - MPI_CHK( mpi_sub_mpi( &X, &LL, &P->X ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &P->X ) ); - - /* - * Y = L * (P.X - X) - P.Y - */ - MPI_CHK( mpi_sub_mpi( &Y, &P->X, &X) ); - MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) ); - MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) ); - - /* - * R = (X mod p, Y mod p) - */ - R->is_zero = 0; - MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) ); - MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); - -cleanup: - - mpi_free( &LN ); mpi_free( &LD ); mpi_free( &K ); mpi_free( &L ); - mpi_free( &LL ); mpi_free( &X ); mpi_free( &Y ); - - return( ret ); -} - /* * Addition: R = P + Q, cf p. 7 of SEC1 v2 */ @@ -403,6 +411,9 @@ int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ) { int ret = 0; + ecp_ptjac J; + + ecp_ptjac_init( &J ); if( P->is_zero ) { @@ -416,8 +427,7 @@ int ecp_add( const ecp_group *grp, ecp_point *R, { ret = ecp_add_generic( grp, R, P, Q ); } - else if( mpi_cmp_int( &P->Y, 0 ) == 0 || - mpi_cmp_mpi( &P->Y, &Q->Y ) != 0 ) + else if( mpi_cmp_mpi( &P->Y, &Q->Y ) != 0 ) { ecp_set_zero( R ); } @@ -426,15 +436,20 @@ int ecp_add( const ecp_group *grp, ecp_point *R, /* * P == Q */ - ret = ecp_double_generic( grp, R, P ); + ecp_aff_to_jac( &J, P ); + MPI_CHK( ecp_double_jac( grp, &J, &J ) ); + MPI_CHK( ecp_jac_to_aff( grp, R, &J ) ); } +cleanup: + + ecp_ptjac_free( &J ); + return ret; } /* - * Integer multiplication: R = m * P - * GECC 5.7 (SPA-resistant algorithm) + * Integer multiplication: R = m * P (GECC 5.7, SPA-resistant variant) */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ) @@ -455,7 +470,7 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, ecp_set_zero( &Q[0] ); - for( pos = mpi_msb( m ) - 1; ; pos-- ) + for( pos = mpi_msb( m ) - 1 ; ; pos-- ) { MPI_CHK( ecp_add( grp, &Q[0], &Q[0], &Q[0] ) ); MPI_CHK( ecp_add( grp, &Q[1], &Q[0], P ) ); From 7e0adfbcc5bf444457049620f75b8aea40d78adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 23:21:46 +0100 Subject: [PATCH 23/76] Replaced add_generic with add_mixed --- library/ecp.c | 174 ++++++++++++++++++++++++++------------------------ 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 3541f0b8e..92599e5b7 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -225,13 +225,43 @@ static void ecp_ptjac_init( ecp_ptjac *P ) } /* - * Free a point in Jacobian cooridnates + * Free a point in Jacobian coordinates */ static void ecp_ptjac_free( ecp_ptjac *P ) { mpi_free( &P->X ); mpi_free( &P->Y ); mpi_free( &P->Z ); } +/* + * Copy P to R in Jacobian coordinates + */ +static int ecp_ptjac_copy( ecp_ptjac *R, const ecp_ptjac *P ) +{ + int ret = 0; + + MPI_CHK( mpi_copy( &R->X, &P->X ) ); + MPI_CHK( mpi_copy( &R->Y, &P->Y ) ); + MPI_CHK( mpi_copy( &R->Z, &P->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Set P to zero in Jacobian coordinates + */ +static int ecp_ptjac_set_zero( ecp_ptjac *P ) +{ + int ret = 0; + + MPI_CHK( mpi_lset( &P->X, 1 ) ); + MPI_CHK( mpi_lset( &P->Y, 1 ) ); + MPI_CHK( mpi_lset( &P->Z, 0 ) ); + +cleanup: + return( ret ); +} + /* * Convert from affine to Jacobian coordinates */ @@ -240,17 +270,11 @@ static int ecp_aff_to_jac( ecp_ptjac *jac, const ecp_point *aff ) int ret = 0; if( aff->is_zero ) - { - MPI_CHK( mpi_lset( &jac->X, 1 ) ); - MPI_CHK( mpi_lset( &jac->Y, 1 ) ); - MPI_CHK( mpi_lset( &jac->Z, 0 ) ); - } - else - { - MPI_CHK( mpi_copy( &jac->X, &aff->X ) ); - MPI_CHK( mpi_copy( &jac->Y, &aff->Y ) ); - MPI_CHK( mpi_lset( &jac->Z, 1 ) ); - } + return( ecp_ptjac_set_zero( jac ) ); + + MPI_CHK( mpi_copy( &jac->X, &aff->X ) ); + MPI_CHK( mpi_copy( &jac->Y, &aff->Y ) ); + MPI_CHK( mpi_lset( &jac->Z, 1 ) ); cleanup: return( ret ); @@ -305,17 +329,12 @@ static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, int ret = 0; mpi T1, T2, T3, X, Y, Z; + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( ecp_ptjac_set_zero( R ) ); + mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); - if( mpi_cmp_int( &P->Z, 0 ) == 0 ) - { - MPI_CHK( mpi_lset( &R->X, 1 ) ); - MPI_CHK( mpi_lset( &R->Y, 1 ) ); - MPI_CHK( mpi_lset( &R->Z, 0 ) ); - goto cleanup; - } - MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MPI_CHK( mpi_sub_mpi( &T2, &P->X, &T1 ) ); MPI_CHK( mpi_add_mpi( &T1, &P->X, &T1 ) ); @@ -349,63 +368,74 @@ cleanup: } /* - * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0) - * Cf SEC1 v2 p. 7, item 4 + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) */ -static int ecp_add_generic( const ecp_group *grp, ecp_point *R, - const ecp_point *P, const ecp_point *Q ) +static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, + const ecp_ptjac *P, const ecp_point *Q ) { int ret = 0; - mpi DX, DY, K, L, LL, X, Y; - - mpi_init( &DX ); mpi_init( &DY ); mpi_init( &K ); mpi_init( &L ); - mpi_init( &LL ); mpi_init( &X ); mpi_init( &Y ); + mpi T1, T2, T3, T4, X, Y, Z; /* - * L = (Q.Y - P.Y) / (Q.X - P.X) mod p + * Trivial cases: P == 0 or Q == 0 */ - MPI_CHK( mpi_sub_mpi( &DY, &Q->Y, &P->Y ) ); - MPI_CHK( mpi_sub_mpi( &DX, &Q->X, &P->X ) ); - MPI_CHK( mpi_inv_mod( &K, &DX, &grp->P ) ); - MPI_CHK( mpi_mul_mpi( &K, &K, &DY ) ); - MPI_CHK( mpi_mod_mpi( &L, &K, &grp->P ) ); + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( ecp_aff_to_jac( R, Q ) ); - /* - * LL = L^2 mod p - */ - MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) ); - MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) ); + if( Q->is_zero ) + return( ecp_ptjac_copy( R, P ) ); - /* - * X = L^2 - P.X - Q.X - */ - MPI_CHK( mpi_sub_mpi( &X, &LL, &P->X ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &Q->X ) ); + mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); - /* - * Y = L * (P.X - X) - P.Y - */ - MPI_CHK( mpi_sub_mpi( &Y, &P->X, &X) ); - MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) ); - MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) ); + MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); + MPI_CHK( mpi_mul_mpi( &T2, &T1, &P->Z ) ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &Q->X ) ); + MPI_CHK( mpi_mul_mpi( &T2, &T2, &Q->Y ) ); + MPI_CHK( mpi_sub_mpi( &T1, &T1, &P->X ) ); + MPI_CHK( mpi_sub_mpi( &T2, &T2, &P->Y ) ); + + 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_ptjac_set_zero( R ); + goto cleanup; + } + } + + MPI_CHK( mpi_mul_mpi( &Z, &P->Z, &T1 ) ); + MPI_CHK( mpi_mul_mpi( &T3, &T1, &T1 ) ); + MPI_CHK( mpi_mul_mpi( &T4, &T3, &T1 ) ); + MPI_CHK( mpi_mul_mpi( &T3, &T3, &P->X ) ); + MPI_CHK( mpi_mul_int( &T1, &T3, 2 ) ); + MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T4 ) ); + MPI_CHK( mpi_sub_mpi( &T3, &T3, &X ) ); + MPI_CHK( mpi_mul_mpi( &T3, &T3, &T2 ) ); + MPI_CHK( mpi_mul_mpi( &T4, &T4, &P->Y ) ); + MPI_CHK( mpi_sub_mpi( &Y, &T3, &T4 ) ); - /* - * R = (X mod p, Y mod p) - */ - R->is_zero = 0; MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) ); MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); + MPI_CHK( mpi_mod_mpi( &R->Z, &Z, &grp->P ) ); cleanup: - mpi_free( &DX ); mpi_free( &DY ); mpi_free( &K ); mpi_free( &L ); - mpi_free( &LL ); mpi_free( &X ); mpi_free( &Y ); + 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, cf p. 7 of SEC1 v2 + * Addition: R = P + Q, affine wrapper */ int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ) @@ -415,37 +445,15 @@ int ecp_add( const ecp_group *grp, ecp_point *R, ecp_ptjac_init( &J ); - if( P->is_zero ) - { - ret = ecp_copy( R, Q ); - } - else if( Q->is_zero ) - { - ret = ecp_copy( R, P ); - } - else if( mpi_cmp_mpi( &P->X, &Q->X ) != 0 ) - { - ret = ecp_add_generic( grp, R, P, Q ); - } - else if( mpi_cmp_mpi( &P->Y, &Q->Y ) != 0 ) - { - ecp_set_zero( R ); - } - else - { - /* - * P == Q - */ - ecp_aff_to_jac( &J, P ); - MPI_CHK( ecp_double_jac( grp, &J, &J ) ); - MPI_CHK( ecp_jac_to_aff( grp, R, &J ) ); - } + MPI_CHK( ecp_aff_to_jac( &J, P ) ); + MPI_CHK( ecp_add_mixed( grp, &J, &J, Q ) ); + MPI_CHK( ecp_jac_to_aff( grp, R, &J ) ); cleanup: ecp_ptjac_free( &J ); - return ret; + return( ret ); } /* From e0c16922f934b864a034f11d4e0d2db4d008d80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Nov 2012 23:27:28 +0100 Subject: [PATCH 24/76] Point multiplication using Jacobian coordinates --- include/polarssl/ecp.h | 6 ------ library/ecp.c | 16 ++++++++-------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 8763fc18f..0de84aae9 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -245,9 +245,6 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ); * * \return 0 if successful, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO (shouldn't happen) - * (temporary, a faster version not using division will be - * used in the future) */ int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ); @@ -262,9 +259,6 @@ int ecp_add( const ecp_group *grp, ecp_point *R, * * \return 0 if successful, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO (shouldn't happen) - * (temporary, a faster version not using division will be - * used in the future) */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); diff --git a/library/ecp.c b/library/ecp.c index 92599e5b7..d64fd0552 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -464,9 +464,9 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, { int ret = 0; size_t pos; - ecp_point Q[2]; + ecp_ptjac Q[2]; - ecp_point_init( &Q[0] ); ecp_point_init( &Q[1] ); + ecp_ptjac_init( &Q[0] ); ecp_ptjac_init( &Q[1] ); /* * The general method works only for m >= 1 @@ -476,23 +476,23 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, goto cleanup; } - ecp_set_zero( &Q[0] ); + ecp_ptjac_set_zero( &Q[0] ); for( pos = mpi_msb( m ) - 1 ; ; pos-- ) { - MPI_CHK( ecp_add( grp, &Q[0], &Q[0], &Q[0] ) ); - MPI_CHK( ecp_add( grp, &Q[1], &Q[0], P ) ); - MPI_CHK( ecp_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); + MPI_CHK( ecp_double_jac( grp, &Q[0], &Q[0] ) ); + MPI_CHK( ecp_add_mixed( grp, &Q[1], &Q[0], P ) ); + MPI_CHK( ecp_ptjac_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); if( pos == 0 ) break; } - MPI_CHK( ecp_copy( R, &Q[0] ) ); + MPI_CHK( ecp_jac_to_aff( grp, R, &Q[0] ) ); cleanup: - ecp_point_free( &Q[0] ); ecp_point_free( &Q[1] ); + ecp_ptjac_free( &Q[0] ); ecp_ptjac_free( &Q[1] ); return( ret ); } From 84d1aea1acb1ce253b981cc4ea07a3d8481d877d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 9 Nov 2012 02:09:38 +0100 Subject: [PATCH 25/76] Now reducing mod p after every single operation --- library/ecp.c | 125 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 50 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index d64fd0552..01076a186 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -206,6 +206,25 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) return( POLARSSL_ERR_ECP_GENERIC ); } +/* + * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi + */ +#define MOD_MUL( N ) MPI_CHK( mpi_mod_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mpi mod p in-place, to use after mpi_sub_mpi + */ +#define MOD_SUB( N ) \ + while( 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 + */ +#define MOD_ADD( N ) \ + while( mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) ) + /* * Internal point format used for fast addition/doubling/multiplication: * Jacobian coordinates (GECC example 3.20) @@ -274,7 +293,7 @@ static int ecp_aff_to_jac( ecp_ptjac *jac, const ecp_point *aff ) MPI_CHK( mpi_copy( &jac->X, &aff->X ) ); MPI_CHK( mpi_copy( &jac->Y, &aff->Y ) ); - MPI_CHK( mpi_lset( &jac->Z, 1 ) ); + MPI_CHK( mpi_lset( &jac->Z, 1 ) ); cleanup: return( ret ); @@ -301,17 +320,15 @@ static int ecp_jac_to_aff( const ecp_group *grp, /* * aff.X = jac.X / (jac.Z)^2 mod p */ - MPI_CHK( mpi_inv_mod( &Zi, &jac->Z, &grp->P ) ); - MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); - MPI_CHK( mpi_mul_mpi( &T, &jac->X, &ZZi ) ); - MPI_CHK( mpi_mod_mpi( &aff->X, &T, &grp->P ) ); + MPI_CHK( mpi_inv_mod( &Zi, &jac->Z, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MPI_CHK( mpi_mul_mpi( &aff->X, &jac->X, &ZZi ) ); MOD_MUL( aff->X ); /* * aff.Y = jac.Y / (jac.Z)^3 mod p */ - MPI_CHK( mpi_mul_mpi( &T, &jac->Y, &ZZi ) ); - MPI_CHK( mpi_mul_mpi( &T, &T, &Zi ) ); - MPI_CHK( mpi_mod_mpi( &aff->Y, &T, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &aff->Y, &jac->Y, &ZZi ) ); MOD_MUL( aff->Y ); + MPI_CHK( mpi_mul_mpi( &aff->Y, &aff->Y, &Zi ) ); MOD_MUL( aff->Y ); cleanup: @@ -335,29 +352,37 @@ static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); - MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); - MPI_CHK( mpi_sub_mpi( &T2, &P->X, &T1 ) ); - MPI_CHK( mpi_add_mpi( &T1, &P->X, &T1 ) ); - MPI_CHK( mpi_mul_mpi( &T2, &T2, &T1 ) ); - MPI_CHK( mpi_mul_int( &T2, &T2, 3 ) ); + MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_sub_mpi( &T2, &P->X, &T1 ) ); MOD_SUB( T2 ); + MPI_CHK( mpi_add_mpi( &T1, &P->X, &T1 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_mul_mpi( &T2, &T2, &T1 ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_mul_int( &T2, &T2, 3 ) ); MOD_ADD( T2 ); MPI_CHK( mpi_copy ( &Y, &P->Y ) ); - MPI_CHK( mpi_shift_l( &Y, 1 ) ); - MPI_CHK( mpi_mul_mpi( &Z, &Y, &P->Z ) ); - MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); - MPI_CHK( mpi_mul_mpi( &T3, &Y, &P->X ) ); - MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); - MPI_CHK( mpi_copy ( &T1, &T3 ) ); - MPI_CHK( mpi_shift_l( &T1, 1 ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); - MPI_CHK( mpi_sub_mpi( &T1, &T3, &X ) ); - MPI_CHK( mpi_mul_mpi( &T1, &T1, &T2 ) ); - MPI_CHK( mpi_sub_mpi( &Y, &T1, &Y ) ); + MPI_CHK( mpi_shift_l( &Y, 1 ) ); MOD_ADD( Y ); + MPI_CHK( mpi_mul_mpi( &Z, &Y, &P->Z ) ); MOD_MUL( Z ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); MOD_MUL( Y ); + MPI_CHK( mpi_mul_mpi( &T3, &Y, &P->X ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); MOD_MUL( Y ); - MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) ); - MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); - MPI_CHK( mpi_mod_mpi( &R->Z, &Z, &grp->P ) ); + /* + * For Y = Y / 2 mod p, we must make sure that Y is even before + * using right-shift. No need to reduce mod p afterwards. + */ + if( mpi_get_bit( &Y, 0 ) == 1 ) + MPI_CHK( mpi_add_mpi( &Y, &Y, &grp->P ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + + MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MPI_CHK( mpi_copy ( &T1, &T3 ) ); + MPI_CHK( mpi_shift_l( &T1, 1 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MPI_CHK( mpi_sub_mpi( &T1, &T3, &X ) ); MOD_SUB( T1 ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &T2 ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_sub_mpi( &Y, &T1, &Y ) ); 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: @@ -388,12 +413,12 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, 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 ) ); - MPI_CHK( mpi_mul_mpi( &T2, &T1, &P->Z ) ); - MPI_CHK( mpi_mul_mpi( &T1, &T1, &Q->X ) ); - MPI_CHK( mpi_mul_mpi( &T2, &T2, &Q->Y ) ); - MPI_CHK( mpi_sub_mpi( &T1, &T1, &P->X ) ); - MPI_CHK( mpi_sub_mpi( &T2, &T2, &P->Y ) ); + 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 ); if( mpi_cmp_int( &T1, 0 ) == 0 ) { @@ -409,22 +434,22 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, } } - MPI_CHK( mpi_mul_mpi( &Z, &P->Z, &T1 ) ); - MPI_CHK( mpi_mul_mpi( &T3, &T1, &T1 ) ); - MPI_CHK( mpi_mul_mpi( &T4, &T3, &T1 ) ); - MPI_CHK( mpi_mul_mpi( &T3, &T3, &P->X ) ); - MPI_CHK( mpi_mul_int( &T1, &T3, 2 ) ); - MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T4 ) ); - MPI_CHK( mpi_sub_mpi( &T3, &T3, &X ) ); - MPI_CHK( mpi_mul_mpi( &T3, &T3, &T2 ) ); - MPI_CHK( mpi_mul_mpi( &T4, &T4, &P->Y ) ); - MPI_CHK( mpi_sub_mpi( &Y, &T3, &T4 ) ); + 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_mod_mpi( &R->X, &X, &grp->P ) ); - MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) ); - MPI_CHK( mpi_mod_mpi( &R->Z, &Z, &grp->P ) ); + MPI_CHK( mpi_copy( &R->X, &X ) ); + MPI_CHK( mpi_copy( &R->Y, &Y ) ); + MPI_CHK( mpi_copy( &R->Z, &Z ) ); cleanup: From 62aad14139cfc7a62d782dbad1245dee8ff55f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 10 Nov 2012 00:27:12 +0100 Subject: [PATCH 26/76] Added slot for fast modp, with mod_p521 --- include/polarssl/ecp.h | 8 +++-- library/ecp.c | 82 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 0de84aae9..d30dd0b3f 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -54,6 +54,8 @@ ecp_point; * * The curves we consider are defined by y^2 = x^3 - 3x + b mod p, * and a generator for a large subgroup is fixed. + * + * modp may be NULL; pbits will not be used in this case. */ typedef struct { @@ -61,6 +63,8 @@ typedef struct mpi B; /*!< constant term in the equation */ ecp_point G; /*!< generator of the subgroup used */ mpi N; /*!< the order of G */ + int (*modp)(mpi *); /*!< function for fast reduction mod P */ + unsigned pbits; /*!< number of bits in P */ } ecp_group; @@ -244,7 +248,7 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ); * \param Q Right-hand point * * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed */ int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ); @@ -258,7 +262,7 @@ int ecp_add( const ecp_group *grp, ecp_point *R, * \param P Point to multiply * * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); diff --git a/library/ecp.c b/library/ecp.c index 01076a186..a22f1cc61 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -28,6 +28,7 @@ * * 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 */ #include "polarssl/config.h" @@ -61,6 +62,9 @@ void ecp_group_init( ecp_group *grp ) mpi_init( &grp->B ); ecp_point_init( &grp->G ); mpi_init( &grp->N ); + + grp->modp = NULL; + grp->pbits = 0; } /* @@ -154,6 +158,80 @@ cleanup: return( ret ); } +/* + * Wrapper around fast quasi-modp functions, with fallback to mpi_mod_mpi + * + * The quasi-modp functions expect an mpi N such that 0 <= N < 2^(2*pbits) + * and change it in-place so that it can easily be brought in the 0..P-1 + * range by a few additions or substractions. + */ +static int ecp_modp( mpi *N, const ecp_group *grp ) +{ + int ret = 0; + + if( grp->modp == NULL ) + return( mpi_mod_mpi( N, N, &grp->P ) ); + + if( mpi_cmp_int( N, 0 ) < 0 || mpi_msb( N ) > 2 * grp->pbits ) + return( POLARSSL_ERR_ECP_GENERIC ); + + MPI_CHK( grp->modp( N ) ); + + while( mpi_cmp_int( N, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( N, N, &grp->P ) ); + + while( mpi_cmp_mpi( N, &grp->P ) >= 0 ) + MPI_CHK( mpi_sub_mpi( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Size of p521 in terms of t_uint + */ +#define P521_SIZE_INT ( 521 / (sizeof( t_uint ) << 3) + 1 ) + +/* + * Bits to keep in the most significant t_uint + */ +#if defined(POLARSS_HAVE_INT8) +#define P521_MASK 0x01 +#else +#define P521_MASK 0x01FF +#endif + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * + * It is required that 0 <= N < 2^(2*521) on entry. + * On exit, it is only guaranteed that 0 <= N < 2^(521+1). + */ +static int ecp_mod_p521( mpi *N ) +{ + int ret = 0; + t_uint Mp[P521_SIZE_INT]; + mpi M; + + if( N->n < P521_SIZE_INT ) + return( 0 ); + + memset( Mp, 0, P521_SIZE_INT * sizeof( t_uint ) ); + memcpy( Mp, N->p, P521_SIZE_INT * sizeof( t_uint ) ); + Mp[P521_SIZE_INT - 1] &= P521_MASK; + + M.s = 1; + M.n = P521_SIZE_INT; + M.p = Mp; + + MPI_CHK( mpi_shift_r( N, 521 ) ); + + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + /* * Set a group using well-known domain parameters */ @@ -194,6 +272,8 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) POLARSSL_ECP_SECP384R1_N ) ); case POLARSSL_ECP_DP_SECP521R1: + grp->modp = ecp_mod_p521; + grp->pbits = 521; return( ecp_group_read_string( grp, 16, POLARSSL_ECP_SECP521R1_P, POLARSSL_ECP_SECP521R1_B, @@ -209,7 +289,7 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) /* * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi */ -#define MOD_MUL( N ) MPI_CHK( mpi_mod_mpi( &N, &N, &grp->P ) ) +#define MOD_MUL( N ) MPI_CHK( ecp_modp( &N, grp ) ) /* * Reduce a mpi mod p in-place, to use after mpi_sub_mpi From dada4da33f856b25a2c7754a83485a35876777f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 10 Nov 2012 14:23:17 +0100 Subject: [PATCH 27/76] Moved domain paramaters to ecp.c --- include/polarssl/ecp.h | 72 +------------------- library/ecp.c | 148 +++++++++++++++++++++++++++++++---------- 2 files changed, 113 insertions(+), 107 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index d30dd0b3f..6a504f1de 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -77,7 +77,7 @@ ecp_group; * * \warning This library does not support validation of arbitrary domain * parameters. Therefore, only well-known domain parameters from trusted - * sources (such as the ones below) should be used. + * sources (such as the ones below) should be used. See ecp_use_known_dp(). */ #define POLARSSL_ECP_DP_SECP192R1 0 #define POLARSSL_ECP_DP_SECP224R1 1 @@ -85,76 +85,6 @@ ecp_group; #define POLARSSL_ECP_DP_SECP384R1 3 #define POLARSSL_ECP_DP_SECP521R1 4 -#define POLARSSL_ECP_SECP192R1_P \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF" -#define POLARSSL_ECP_SECP192R1_B \ - "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1" -#define POLARSSL_ECP_SECP192R1_GX \ - "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" -#define POLARSSL_ECP_SECP192R1_GY \ - "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811" -#define POLARSSL_ECP_SECP192R1_N \ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831" - -#define POLARSSL_ECP_SECP224R1_P \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001" -#define POLARSSL_ECP_SECP224R1_B \ - "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4" -#define POLARSSL_ECP_SECP224R1_GX \ - "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" -#define POLARSSL_ECP_SECP224R1_GY \ - "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34" -#define POLARSSL_ECP_SECP224R1_N \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D" - -#define POLARSSL_ECP_SECP256R1_P \ - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" -#define POLARSSL_ECP_SECP256R1_B \ - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B" -#define POLARSSL_ECP_SECP256R1_GX \ - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" -#define POLARSSL_ECP_SECP256R1_GY \ - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" -#define POLARSSL_ECP_SECP256R1_N \ - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551" - -#define POLARSSL_ECP_SECP384R1_P \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF" -#define POLARSSL_ECP_SECP384R1_B \ - "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE814112" \ - "0314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF" -#define POLARSSL_ECP_SECP384R1_GX \ - "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B98" \ - "59F741E082542A385502F25DBF55296C3A545E3872760AB7" -#define POLARSSL_ECP_SECP384R1_GY \ - "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147C" \ - "E9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F" -#define POLARSSL_ECP_SECP384R1_N \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "C7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973" - -#define POLARSSL_ECP_SECP521R1_P \ - "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" -#define POLARSSL_ECP_SECP521R1_B \ - "00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B" \ - "99B315F3B8B489918EF109E156193951EC7E937B1652C0BD" \ - "3BB1BF073573DF883D2C34F1EF451FD46B503F00" -#define POLARSSL_ECP_SECP521R1_GX \ - "000000C6858E06B70404E9CD9E3ECB662395B4429C648139" \ - "053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127" \ - "A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" -#define POLARSSL_ECP_SECP521R1_GY \ - "0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449" \ - "579B446817AFBD17273E662C97EE72995EF42640C550B901" \ - "3FAD0761353C7086A272C24088BE94769FD16650" -#define POLARSSL_ECP_SECP521R1_N \ - "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148" \ - "F709A5D03BB5C9B8899C47AEBB6FB71E91386409" - #ifdef __cplusplus extern "C" { #endif diff --git a/library/ecp.c b/library/ecp.c index a22f1cc61..2fe456f82 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -190,7 +190,7 @@ cleanup: /* * Size of p521 in terms of t_uint */ -#define P521_SIZE_INT ( 521 / (sizeof( t_uint ) << 3) + 1 ) +#define P521_SIZE_INT ( 521 / ( sizeof( t_uint ) << 3 ) + 1 ) /* * Bits to keep in the most significant t_uint @@ -203,9 +203,6 @@ cleanup: /* * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) - * - * It is required that 0 <= N < 2^(2*521) on entry. - * On exit, it is only guaranteed that 0 <= N < 2^(521+1). */ static int ecp_mod_p521( mpi *N ) { @@ -232,6 +229,91 @@ cleanup: return( ret ); } +/* + * Domain parameters for secp192r1 + */ +#define SECP192R1_P \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF" +#define SECP192R1_B \ + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1" +#define SECP192R1_GX \ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" +#define SECP192R1_GY \ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811" +#define SECP192R1_N \ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831" + +/* + * Domain parameters for secp224r1 + */ +#define SECP224R1_P \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001" +#define SECP224R1_B \ + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4" +#define SECP224R1_GX \ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" +#define SECP224R1_GY \ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34" +#define SECP224R1_N \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D" + +/* + * Domain parameters for secp256r1 + */ +#define SECP256R1_P \ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" +#define SECP256R1_B \ + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B" +#define SECP256R1_GX \ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" +#define SECP256R1_GY \ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" +#define SECP256R1_N \ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551" + +/* + * Domain parameters for secp384r1 + */ +#define SECP384R1_P \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF" +#define SECP384R1_B \ + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE814112" \ + "0314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF" +#define SECP384R1_GX \ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B98" \ + "59F741E082542A385502F25DBF55296C3A545E3872760AB7" +#define SECP384R1_GY \ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147C" \ + "E9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F" +#define SECP384R1_N \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "C7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973" + +/* + * Domain parameters for secp521r1 + */ +#define SECP521R1_P \ + "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +#define SECP521R1_B \ + "00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B" \ + "99B315F3B8B489918EF109E156193951EC7E937B1652C0BD" \ + "3BB1BF073573DF883D2C34F1EF451FD46B503F00" +#define SECP521R1_GX \ + "000000C6858E06B70404E9CD9E3ECB662395B4429C648139" \ + "053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127" \ + "A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" +#define SECP521R1_GY \ + "0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449" \ + "579B446817AFBD17273E662C97EE72995EF42640C550B901" \ + "3FAD0761353C7086A272C24088BE94769FD16650" +#define SECP521R1_N \ + "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ + "FFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148" \ + "F709A5D03BB5C9B8899C47AEBB6FB71E91386409" + /* * Set a group using well-known domain parameters */ @@ -241,51 +323,45 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) { case POLARSSL_ECP_DP_SECP192R1: return( ecp_group_read_string( grp, 16, - POLARSSL_ECP_SECP192R1_P, - POLARSSL_ECP_SECP192R1_B, - POLARSSL_ECP_SECP192R1_GX, - POLARSSL_ECP_SECP192R1_GY, - POLARSSL_ECP_SECP192R1_N ) - ); + SECP192R1_P, SECP192R1_B, + SECP192R1_GX, SECP192R1_GY, SECP192R1_N ) ); + case POLARSSL_ECP_DP_SECP224R1: return( ecp_group_read_string( grp, 16, - POLARSSL_ECP_SECP224R1_P, - POLARSSL_ECP_SECP224R1_B, - POLARSSL_ECP_SECP224R1_GX, - POLARSSL_ECP_SECP224R1_GY, - POLARSSL_ECP_SECP224R1_N ) - ); + SECP224R1_P, SECP224R1_B, + SECP224R1_GX, SECP224R1_GY, SECP224R1_N ) ); + case POLARSSL_ECP_DP_SECP256R1: return( ecp_group_read_string( grp, 16, - POLARSSL_ECP_SECP256R1_P, - POLARSSL_ECP_SECP256R1_B, - POLARSSL_ECP_SECP256R1_GX, - POLARSSL_ECP_SECP256R1_GY, - POLARSSL_ECP_SECP256R1_N ) - ); + SECP256R1_P, SECP256R1_B, + SECP256R1_GX, SECP256R1_GY, SECP256R1_N ) ); + case POLARSSL_ECP_DP_SECP384R1: return( ecp_group_read_string( grp, 16, - POLARSSL_ECP_SECP384R1_P, - POLARSSL_ECP_SECP384R1_B, - POLARSSL_ECP_SECP384R1_GX, - POLARSSL_ECP_SECP384R1_GY, - POLARSSL_ECP_SECP384R1_N ) - ); + SECP384R1_P, SECP384R1_B, + SECP384R1_GX, SECP384R1_GY, SECP384R1_N ) ); + case POLARSSL_ECP_DP_SECP521R1: grp->modp = ecp_mod_p521; grp->pbits = 521; return( ecp_group_read_string( grp, 16, - POLARSSL_ECP_SECP521R1_P, - POLARSSL_ECP_SECP521R1_B, - POLARSSL_ECP_SECP521R1_GX, - POLARSSL_ECP_SECP521R1_GY, - POLARSSL_ECP_SECP521R1_N ) - ); + SECP521R1_P, SECP521R1_B, + SECP521R1_GX, SECP521R1_GY, SECP521R1_N ) ); } return( POLARSSL_ERR_ECP_GENERIC ); } +/* + * Fast mod-p functions expect an argument in the 0 .. p^2 range. + * + * In order to garantee 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 helpers for that. + */ + /* * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi */ @@ -306,8 +382,8 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) ) /* - * Internal point format used for fast addition/doubling/multiplication: - * Jacobian coordinates (GECC example 3.20) + * Internal point format used for fast (that is, without mpi_inv_mod) + * addition/doubling/multiplication: Jacobian coordinates (GECC ex 3.20) */ typedef struct { From 471232577795a4b2e27eb84dc552eb3821f3c5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 10 Nov 2012 14:44:24 +0100 Subject: [PATCH 28/76] Clarifications in comments; code cosmetics & style --- include/polarssl/ecp.h | 14 +++-- library/ecp.c | 118 +++++++++++++++++++---------------------- 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 6a504f1de..a7f6258cb 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -55,7 +55,15 @@ ecp_point; * The curves we consider are defined by y^2 = x^3 - 3x + b mod p, * and a generator for a large subgroup is fixed. * - * modp may be NULL; pbits will not be used in this case. + * If modp is NULL, pbits will not be used, and reduction modulo P is + * done using a generic algorithm. + * + * If modp is not NULL, pbits must be the size of P in bits and modp + * must be a function that takes an mpi in the range 0..2^(2*pbits) 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 range by a + * few additions or substractions. It must return 0 on success and a + * POLARSSL_ERR_ECP_XXX error on failure. */ typedef struct { @@ -77,7 +85,7 @@ ecp_group; * * \warning This library does not support validation of arbitrary domain * parameters. Therefore, only well-known domain parameters from trusted - * sources (such as the ones below) should be used. See ecp_use_known_dp(). + * sources should be used. See ecp_use_known_dp(). */ #define POLARSSL_ECP_DP_SECP192R1 0 #define POLARSSL_ECP_DP_SECP224R1 1 @@ -161,7 +169,7 @@ int ecp_group_read_string( ecp_group *grp, int radix, * \param grp Destination group * \param index Index in the list of well-known domain parameters * - * \return O if successul, + * \return O if successful, * POLARSSL_ERR_MPI_XXX if initialization failed * POLARSSL_ERR_ECP_GENERIC if index is out of range * diff --git a/library/ecp.c b/library/ecp.c index 2fe456f82..574b181db 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -109,11 +109,11 @@ void ecp_set_zero( ecp_point *pt ) */ int ecp_copy( ecp_point *P, const ecp_point *Q ) { - int ret = 0; + int ret; if( Q->is_zero ) { ecp_set_zero( P ); - return( ret ); + return( 0 ); } P->is_zero = Q->is_zero; @@ -130,7 +130,7 @@ cleanup: int ecp_point_read_string( ecp_point *P, int radix, const char *x, const char *y ) { - int ret = 0; + int ret; P->is_zero = 0; MPI_CHK( mpi_read_string( &P->X, radix, x ) ); @@ -147,7 +147,7 @@ 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 = 0; + int ret; MPI_CHK( mpi_read_string( &grp->P, radix, p ) ); MPI_CHK( mpi_read_string( &grp->B, radix, b ) ); @@ -159,15 +159,11 @@ cleanup: } /* - * Wrapper around fast quasi-modp functions, with fallback to mpi_mod_mpi - * - * The quasi-modp functions expect an mpi N such that 0 <= N < 2^(2*pbits) - * and change it in-place so that it can easily be brought in the 0..P-1 - * range by a few additions or substractions. + * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi */ static int ecp_modp( mpi *N, const ecp_group *grp ) { - int ret = 0; + int ret; if( grp->modp == NULL ) return( mpi_mod_mpi( N, N, &grp->P ) ); @@ -206,7 +202,7 @@ cleanup: */ static int ecp_mod_p521( mpi *N ) { - int ret = 0; + int ret; t_uint Mp[P521_SIZE_INT]; mpi M; @@ -353,13 +349,13 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) } /* - * Fast mod-p functions expect an argument in the 0 .. p^2 range. + * Fast mod-p functions expect their argument to be in the 0..p^2 range. * - * In order to garantee that, we need to ensure that operands of - * mpi_mul_mpi are in the 0 .. p range. So, after each operation we will + * 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 helpers for that. + * The following macros are shortcuts for doing that. */ /* @@ -412,7 +408,7 @@ static void ecp_ptjac_free( ecp_ptjac *P ) */ static int ecp_ptjac_copy( ecp_ptjac *R, const ecp_ptjac *P ) { - int ret = 0; + int ret; MPI_CHK( mpi_copy( &R->X, &P->X ) ); MPI_CHK( mpi_copy( &R->Y, &P->Y ) ); @@ -427,7 +423,7 @@ cleanup: */ static int ecp_ptjac_set_zero( ecp_ptjac *P ) { - int ret = 0; + int ret; MPI_CHK( mpi_lset( &P->X, 1 ) ); MPI_CHK( mpi_lset( &P->Y, 1 ) ); @@ -442,7 +438,7 @@ cleanup: */ static int ecp_aff_to_jac( ecp_ptjac *jac, const ecp_point *aff ) { - int ret = 0; + int ret; if( aff->is_zero ) return( ecp_ptjac_set_zero( jac ) ); @@ -461,7 +457,7 @@ cleanup: static int ecp_jac_to_aff( const ecp_group *grp, ecp_point *aff, const ecp_ptjac *jac ) { - int ret = 0; + int ret; mpi Zi, ZZi, T; if( mpi_cmp_int( &jac->Z, 0 ) == 0 ) { @@ -499,7 +495,7 @@ cleanup: static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, const ecp_ptjac *P ) { - int ret = 0; + int ret; mpi T1, T2, T3, X, Y, Z; if( mpi_cmp_int( &P->Z, 0 ) == 0 ) @@ -508,17 +504,16 @@ static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); 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_sub_mpi( &T2, &P->X, &T1 ) ); MOD_SUB( T2 ); - MPI_CHK( mpi_add_mpi( &T1, &P->X, &T1 ) ); MOD_ADD( T1 ); - MPI_CHK( mpi_mul_mpi( &T2, &T2, &T1 ) ); MOD_MUL( T2 ); - MPI_CHK( mpi_mul_int( &T2, &T2, 3 ) ); MOD_ADD( T2 ); - MPI_CHK( mpi_copy ( &Y, &P->Y ) ); - MPI_CHK( mpi_shift_l( &Y, 1 ) ); MOD_ADD( Y ); - MPI_CHK( mpi_mul_mpi( &Z, &Y, &P->Z ) ); MOD_MUL( Z ); - MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); MOD_MUL( Y ); - MPI_CHK( mpi_mul_mpi( &T3, &Y, &P->X ) ); MOD_MUL( T3 ); - MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); MOD_MUL( Y ); + MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_sub_mpi( &T2, &P->X, &T1 ) ); MOD_SUB( T2 ); + MPI_CHK( mpi_add_mpi( &T1, &P->X, &T1 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_mul_mpi( &T2, &T2, &T1 ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_mul_int( &T2, &T2, 3 ) ); MOD_ADD( T2 ); + MPI_CHK( mpi_mul_int( &Y, &P->Y, 2 ) ); MOD_ADD( Y ); + MPI_CHK( mpi_mul_mpi( &Z, &Y, &P->Z ) ); MOD_MUL( Z ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); MOD_MUL( Y ); + MPI_CHK( mpi_mul_mpi( &T3, &Y, &P->X ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &Y, &Y, &Y ) ); MOD_MUL( Y ); /* * For Y = Y / 2 mod p, we must make sure that Y is even before @@ -528,13 +523,12 @@ static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, MPI_CHK( mpi_add_mpi( &Y, &Y, &grp->P ) ); MPI_CHK( mpi_shift_r( &Y, 1 ) ); - MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); - MPI_CHK( mpi_copy ( &T1, &T3 ) ); - MPI_CHK( mpi_shift_l( &T1, 1 ) ); MOD_ADD( T1 ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); - MPI_CHK( mpi_sub_mpi( &T1, &T3, &X ) ); MOD_SUB( T1 ); - MPI_CHK( mpi_mul_mpi( &T1, &T1, &T2 ) ); MOD_MUL( T1 ); - MPI_CHK( mpi_sub_mpi( &Y, &T1, &Y ) ); MOD_SUB( Y ); + MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MPI_CHK( mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MPI_CHK( mpi_sub_mpi( &T1, &T3, &X ) ); MOD_SUB( T1 ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &T2 ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_sub_mpi( &Y, &T1, &Y ) ); MOD_SUB( Y ); MPI_CHK( mpi_copy( &R->X, &X ) ); MPI_CHK( mpi_copy( &R->Y, &Y ) ); @@ -554,7 +548,7 @@ cleanup: static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, const ecp_ptjac *P, const ecp_point *Q ) { - int ret = 0; + int ret; mpi T1, T2, T3, T4, X, Y, Z; /* @@ -569,12 +563,12 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, 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 ); + 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 ); if( mpi_cmp_int( &T1, 0 ) == 0 ) { @@ -590,18 +584,18 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, } } - 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_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 ) ); @@ -621,7 +615,7 @@ cleanup: int ecp_add( const ecp_group *grp, ecp_point *R, const ecp_point *P, const ecp_point *Q ) { - int ret = 0; + int ret; ecp_ptjac J; ecp_ptjac_init( &J ); @@ -643,20 +637,20 @@ cleanup: int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ) { - int ret = 0; + int ret; size_t pos; ecp_ptjac Q[2]; - ecp_ptjac_init( &Q[0] ); ecp_ptjac_init( &Q[1] ); - /* * The general method works only for m >= 1 */ if( mpi_cmp_int( m, 0 ) == 0 ) { ecp_set_zero( R ); - goto cleanup; + return( 0 ); } + ecp_ptjac_init( &Q[0] ); ecp_ptjac_init( &Q[1] ); + ecp_ptjac_set_zero( &Q[0] ); for( pos = mpi_msb( m ) - 1 ; ; pos-- ) From 8433824d5f64beefbb3b1f82f0d0442f93e53977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 11 Nov 2012 20:45:18 +0100 Subject: [PATCH 29/76] Added fast mod_p192 --- library/ecp.c | 79 +++++++++++++++++++++++++++- tests/suites/test_suite_ecp.data | 6 +++ tests/suites/test_suite_ecp.function | 31 +++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/library/ecp.c b/library/ecp.c index 574b181db..6ee8ff04e 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -36,6 +36,7 @@ #if defined(POLARSSL_ECP_C) #include "polarssl/ecp.h" +#include /* * Initialize (the components of) a point @@ -183,10 +184,84 @@ cleanup: return( ret ); } +/* + * 192 bits in terms of t_uint + */ +#define P192_SIZE_INT ( 192 / CHAR_BIT / sizeof( t_uint ) ) + +/* + * Table to get S1, S2, S3 of FIPS 186-3 D.2.1: + * -1 means let this chunk be 0 + * a positive value i means A_i. + */ +#define P192_CHUNKS 3 +#define P192_CHUNK_CHAR ( 64 / CHAR_BIT ) +#define P192_CHUNK_INT ( P192_CHUNK_CHAR / sizeof( t_uint ) ) + +const signed char p192_tbl[][P192_CHUNKS] = { + { -1, 3, 3 }, /* S1 */ + { 4, 4, -1 }, /* S2 */ + { 5, 5, 5 }, /* S3 */ +}; + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mpi *N ) +{ + int ret; + unsigned char i, j, offset; + signed char chunk; + mpi tmp, acc; + t_uint tmp_p[P192_SIZE_INT], acc_p[P192_SIZE_INT + 1]; + + tmp.s = 1; + tmp.n = sizeof( tmp_p ) / sizeof( tmp_p[0] ); + tmp.p = tmp_p; + + acc.s = 1; + acc.n = sizeof( acc_p ) / sizeof( acc_p[0] ); + acc.p = acc_p; + + MPI_CHK( mpi_grow( N, P192_SIZE_INT * 2 ) ); + + /* + * acc = T + */ + memset( acc_p, 0, sizeof( acc_p ) ); + memcpy( acc_p, N->p, P192_CHUNK_CHAR * P192_CHUNKS ); + + for( i = 0; i < sizeof( p192_tbl ) / sizeof( p192_tbl[0] ); i++) + { + /* + * tmp = S_i + */ + memset( tmp_p, 0, sizeof( tmp_p ) ); + for( j = 0, offset = P192_CHUNKS - 1; j < P192_CHUNKS; j++, offset-- ) + { + chunk = p192_tbl[i][j]; + if( chunk >= 0 ) + memcpy( tmp_p + offset * P192_CHUNK_INT, + N->p + chunk * P192_CHUNK_INT, + P192_CHUNK_CHAR ); + } + + /* + * acc += tmp + */ + MPI_CHK( mpi_add_abs( &acc, &acc, &tmp ) ); + } + + MPI_CHK( mpi_copy( N, &acc ) ); + +cleanup: + return( ret ); +} + /* * Size of p521 in terms of t_uint */ -#define P521_SIZE_INT ( 521 / ( sizeof( t_uint ) << 3 ) + 1 ) +#define P521_SIZE_INT ( 521 / CHAR_BIT / sizeof( t_uint ) + 1 ) /* * Bits to keep in the most significant t_uint @@ -318,6 +393,8 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) switch( index ) { case POLARSSL_ECP_DP_SECP192R1: + grp->modp = ecp_mod_p192; + grp->pbits = 192; return( ecp_group_read_string( grp, 16, SECP192R1_P, SECP192R1_B, SECP192R1_GX, SECP192R1_GY, SECP192R1_N ) ); diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 41d3145f0..188d55822 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -64,6 +64,12 @@ ecp_small_mul:12:0:17:05 ECP small multiplication #13 ecp_small_mul:13:1:0:0 +ECP mod p192 readable +ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" + +ECP mod p192 random +ecp_fast_mod:SECP192R1:"36CF96B45D706A0954D89E52CE5F38517A2270E0175849B6F3740151D238CCABEF921437E475881D83BB69E4AA258EBD" + ECP test vectors secp192r1 ecp_test_vect:SECP192R1:"323FA3169D8E9C6593F59476BC142000AB5BE0E249C43426":"CD46489ECFD6C105E7B3D32566E2B122E249ABAADD870612":"68887B4877DF51DD4DC3D6FD11F0A26F8FD3844317916E9A":"631F95BB4A67632C9C476EEE9AB695AB240A0499307FCF62":"519A121680E0045466BA21DF2EEE47F5973B500577EF13D5":"FF613AB4D64CEE3A20875BDB10F953F6B30CA072C60AA57F":"AD420182633F8526BFE954ACDA376F05E5FF4F837F54FEBE":"4371545ED772A59741D0EDA32C671112B7FDDD51461FCF32" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index d81ff881e..471bbec79 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -126,3 +126,34 @@ ecp_test_vect:id:dA:xA:yA:dB:xB:yB:xZ:yZ mpi_free( &xB ); mpi_free( &yB ); mpi_free( &xZ ); mpi_free( &yZ ); } END_CASE + +BEGIN_CASE +ecp_fast_mod:id:N +{ + ecp_group grp; + mpi N, R; + + mpi_init( &N ); mpi_init( &R ); + ecp_group_init( &grp ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + TEST_ASSERT( mpi_read_string( &N, 16, {N} ) == 0 ); + + /* + * Store correct result before we touch N + */ + TEST_ASSERT( mpi_mod_mpi( &R, &N, &grp.P ) == 0 ); + + TEST_ASSERT( grp.modp( &N ) == 0 ); + TEST_ASSERT( mpi_msb( &N ) <= grp.pbits + 3 ); + + /* + * Use mod rather than addition/substraction in case previous test fails + */ + TEST_ASSERT( mpi_mod_mpi( &N, &N, &grp.P ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &N, &R ) == 0 ); + + mpi_free( &N ); mpi_free( &R ); + ecp_group_free( &grp ); +} +END_CASE From 4bdd47d2cb65646b6b4555a0e79c8151afd00fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 11 Nov 2012 14:33:59 +0100 Subject: [PATCH 30/76] Multiplication by negative is now forbidden --- include/polarssl/ecp.h | 1 + library/ecp.c | 13 ++++++++---- tests/suites/test_suite_ecp.data | 31 +++++++++++++++------------- tests/suites/test_suite_ecp.function | 4 ++-- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index a7f6258cb..55aa28263 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -201,6 +201,7 @@ int ecp_add( const ecp_group *grp, ecp_point *R, * * \return 0 if successful, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * POLARSSL_ERR_ECP_GENERIC if m < 0 */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); diff --git a/library/ecp.c b/library/ecp.c index 6ee8ff04e..a773416a9 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -709,19 +709,24 @@ cleanup: } /* - * Integer multiplication: R = m * P (GECC 5.7, SPA-resistant variant) + * Integer multiplication: R = m * P (GECC 5.7, SPA-resistant) */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ) { - int ret; + int ret, cmp; size_t pos; ecp_ptjac Q[2]; + cmp = mpi_cmp_int( m, 0 ); + + if( cmp < 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + /* - * The general method works only for m >= 1 + * The general method works only for m != 0 */ - if( mpi_cmp_int( m, 0 ) == 0 ) { + if( cmp == 0 ) { ecp_set_zero( R ); return( 0 ); } diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 188d55822..816df7735 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -22,47 +22,50 @@ ecp_small_add:0:"37":"31":0:"37":"31":0:21:32 ECP small addition #8 ecp_small_add:0:"14":"11":0:"14":"11":0:27:30 +ECP small multiplication negative +ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC + ECP small multiplication #0 -ecp_small_mul:0:1:0:0 +ecp_small_mul:0:1:0:0:0 ECP small multiplication #1 -ecp_small_mul:1:0:17:42 +ecp_small_mul:1:0:17:42:0 ECP small multiplication #2 -ecp_small_mul:2:0:20:01 +ecp_small_mul:2:0:20:01:0 ECP small multiplication #3 -ecp_small_mul:3:0:14:11 +ecp_small_mul:3:0:14:11:0 ECP small multiplication #4 -ecp_small_mul:4:0:34:33 +ecp_small_mul:4:0:34:33:0 ECP small multiplication #5 -ecp_small_mul:5:0:21:32 +ecp_small_mul:5:0:21:32:0 ECP small multiplication #6 -ecp_small_mul:6:0:27:30 +ecp_small_mul:6:0:27:30:0 ECP small multiplication #7 -ecp_small_mul:7:0:27:17 +ecp_small_mul:7:0:27:17:0 ECP small multiplication #8 -ecp_small_mul:8:0:21:15 +ecp_small_mul:8:0:21:15:0 ECP small multiplication #9 -ecp_small_mul:9:0:34:14 +ecp_small_mul:9:0:34:14:0 ECP small multiplication #10 -ecp_small_mul:10:0:14:36 +ecp_small_mul:10:0:14:36:0 ECP small multiplication #11 -ecp_small_mul:11:0:20:46 +ecp_small_mul:11:0:20:46:0 ECP small multiplication #12 -ecp_small_mul:12:0:17:05 +ecp_small_mul:12:0:17:05:0 ECP small multiplication #13 -ecp_small_mul:13:1:0:0 +ecp_small_mul:13:1:0:0:0 ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 471bbec79..ff51a080e 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -54,7 +54,7 @@ ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c END_CASE BEGIN_CASE -ecp_small_mul:m:r_zero:x_r:y_r +ecp_small_mul:m:r_zero:x_r:y_r:ret { ecp_group grp; ecp_point R; @@ -69,7 +69,7 @@ ecp_small_mul:m:r_zero:x_r:y_r TEST_ASSERT( mpi_lset( &m, {m} ) == 0 ); - TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == 0 ); + TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == {ret} ); if( {r_zero} ) TEST_ASSERT( R.is_zero ); From 773ed546a20465e6a908be94393b5db3b0b094c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 18 Nov 2012 13:19:07 +0100 Subject: [PATCH 31/76] Added a nbits member to ecp_group --- include/polarssl/ecp.h | 24 +++++++++++++----------- library/ecp.c | 12 ++++++++---- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 55aa28263..cf79022c1 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -52,18 +52,17 @@ ecp_point; /** * \brief ECP group structure * - * The curves we consider are defined by y^2 = x^3 - 3x + b mod p, - * and a generator for a large subgroup is fixed. + * The curves we consider are defined by y^2 = x^3 - 3x + B mod P, + * and a generator for a large subgroup of order N is fixed. * - * If modp is NULL, pbits will not be used, and reduction modulo P is - * done using a generic algorithm. + * pbits and nbits must be the size of P and N in bits. * - * If modp is not NULL, pbits must be the size of P in bits and modp - * must be a function that takes an mpi in the range 0..2^(2*pbits) 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 range by a - * few additions or substractions. It must return 0 on success and a - * POLARSSL_ERR_ECP_XXX error on failure. + * 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) 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 range by a few additions or substractions. It + * must return 0 on success and a POLARSSL_ERR_ECP_XXX error on failure. */ typedef struct { @@ -71,8 +70,9 @@ typedef struct mpi B; /*!< constant term in the equation */ ecp_point G; /*!< generator of the subgroup used */ mpi N; /*!< the order of G */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in N */ int (*modp)(mpi *); /*!< function for fast reduction mod P */ - unsigned pbits; /*!< number of bits in P */ } ecp_group; @@ -158,6 +158,8 @@ int ecp_point_read_string( ecp_point *P, int radix, * \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, diff --git a/library/ecp.c b/library/ecp.c index a773416a9..68d2f4eb8 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -64,8 +64,10 @@ void ecp_group_init( ecp_group *grp ) ecp_point_init( &grp->G ); mpi_init( &grp->N ); - grp->modp = NULL; grp->pbits = 0; + grp->nbits = 0; + + grp->modp = NULL; } /* @@ -155,12 +157,16 @@ int ecp_group_read_string( ecp_group *grp, int radix, 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: return( ret ); } /* - * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi + * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi. + * See the documentation of struct ecp_group. */ static int ecp_modp( mpi *N, const ecp_group *grp ) { @@ -394,7 +400,6 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) { case POLARSSL_ECP_DP_SECP192R1: grp->modp = ecp_mod_p192; - grp->pbits = 192; return( ecp_group_read_string( grp, 16, SECP192R1_P, SECP192R1_B, SECP192R1_GX, SECP192R1_GY, SECP192R1_N ) ); @@ -416,7 +421,6 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) case POLARSSL_ECP_DP_SECP521R1: grp->modp = ecp_mod_p521; - grp->pbits = 521; return( ecp_group_read_string( grp, 16, SECP521R1_P, SECP521R1_B, SECP521R1_GX, SECP521R1_GY, SECP521R1_N ) ); From 1c2782cc7c751daf79c720ae06dc374c17d369e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 19 Nov 2012 20:16:28 +0100 Subject: [PATCH 32/76] Changed to jacobian coordinates everywhere --- include/polarssl/ecp.h | 15 ++- library/ecp.c | 182 ++++++++------------------- tests/suites/test_suite_ecp.function | 6 +- 3 files changed, 68 insertions(+), 135 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index cf79022c1..cea403af1 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -37,15 +37,19 @@ #define POLARSSL_ERR_ECP_GENERIC -0x007E /**< Generic ECP error */ /** - * \brief ECP point structure (affine coordinates) + * \brief ECP point structure (jacobian coordinates) * - * Note: if the point is zero, X and Y are irrelevant and should be freed. + * \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 { - char is_zero; /*!< true if point at infinity */ mpi X; /*!< the point's X coordinate */ mpi Y; /*!< the point's Y coordinate */ + mpi Z; /*!< the point's Z coordinate */ } ecp_point; @@ -119,8 +123,11 @@ void ecp_group_free( ecp_group *grp ); /** * \brief Set a point to zero + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed */ -void ecp_set_zero( ecp_point *pt ); +int ecp_set_zero( ecp_point *pt ); /** * \brief Copy the contents of point Q into P diff --git a/library/ecp.c b/library/ecp.c index 68d2f4eb8..1c614b56d 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -46,9 +46,9 @@ void ecp_point_init( ecp_point *pt ) if( pt == NULL ) return; - pt->is_zero = 1; mpi_init( &pt->X ); mpi_init( &pt->Y ); + mpi_init( &pt->Z ); } /* @@ -78,9 +78,9 @@ void ecp_point_free( ecp_point *pt ) if( pt == NULL ) return; - pt->is_zero = 1; mpi_free( &( pt->X ) ); mpi_free( &( pt->Y ) ); + mpi_free( &( pt->Z ) ); } /* @@ -100,11 +100,16 @@ void ecp_group_free( ecp_group *grp ) /* * Set point to zero */ -void ecp_set_zero( ecp_point *pt ) +int ecp_set_zero( ecp_point *pt ) { - pt->is_zero = 1; - mpi_free( &pt->X ); - mpi_free( &pt->Y ); + 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 ); } /* @@ -114,14 +119,9 @@ int ecp_copy( ecp_point *P, const ecp_point *Q ) { int ret; - if( Q->is_zero ) { - ecp_set_zero( P ); - return( 0 ); - } - - P->is_zero = Q->is_zero; 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 ); @@ -135,9 +135,9 @@ int ecp_point_read_string( ecp_point *P, int radix, { int ret; - P->is_zero = 0; 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 ); @@ -459,109 +459,35 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) ) /* - * Internal point format used for fast (that is, without mpi_inv_mod) - * addition/doubling/multiplication: Jacobian coordinates (GECC ex 3.20) + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) */ -typedef struct -{ - mpi X, Y, Z; -} -ecp_ptjac; - -/* - * Initialize a point in Jacobian coordinates - */ -static void ecp_ptjac_init( ecp_ptjac *P ) -{ - mpi_init( &P->X ); mpi_init( &P->Y ); mpi_init( &P->Z ); -} - -/* - * Free a point in Jacobian coordinates - */ -static void ecp_ptjac_free( ecp_ptjac *P ) -{ - mpi_free( &P->X ); mpi_free( &P->Y ); mpi_free( &P->Z ); -} - -/* - * Copy P to R in Jacobian coordinates - */ -static int ecp_ptjac_copy( ecp_ptjac *R, const ecp_ptjac *P ) -{ - int ret; - - MPI_CHK( mpi_copy( &R->X, &P->X ) ); - MPI_CHK( mpi_copy( &R->Y, &P->Y ) ); - MPI_CHK( mpi_copy( &R->Z, &P->Z ) ); - -cleanup: - return( ret ); -} - -/* - * Set P to zero in Jacobian coordinates - */ -static int ecp_ptjac_set_zero( ecp_ptjac *P ) -{ - int ret; - - MPI_CHK( mpi_lset( &P->X, 1 ) ); - MPI_CHK( mpi_lset( &P->Y, 1 ) ); - MPI_CHK( mpi_lset( &P->Z, 0 ) ); - -cleanup: - return( ret ); -} - -/* - * Convert from affine to Jacobian coordinates - */ -static int ecp_aff_to_jac( ecp_ptjac *jac, const ecp_point *aff ) -{ - int ret; - - if( aff->is_zero ) - return( ecp_ptjac_set_zero( jac ) ); - - MPI_CHK( mpi_copy( &jac->X, &aff->X ) ); - MPI_CHK( mpi_copy( &jac->Y, &aff->Y ) ); - MPI_CHK( mpi_lset( &jac->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Convert from Jacobian to affine coordinates - */ -static int ecp_jac_to_aff( const ecp_group *grp, - ecp_point *aff, const ecp_ptjac *jac ) +static int ecp_normalize( const ecp_group *grp, ecp_point *pt ) { int ret; mpi Zi, ZZi, T; - if( mpi_cmp_int( &jac->Z, 0 ) == 0 ) { - ecp_set_zero( aff ); + if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) return( 0 ); - } mpi_init( &Zi ); mpi_init( &ZZi ); mpi_init( &T ); - aff->is_zero = 0; + /* + * 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 ); /* - * aff.X = jac.X / (jac.Z)^2 mod p + * Y = Y / Z^3 mod p */ - MPI_CHK( mpi_inv_mod( &Zi, &jac->Z, &grp->P ) ); - MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); - MPI_CHK( mpi_mul_mpi( &aff->X, &jac->X, &ZZi ) ); MOD_MUL( aff->X ); + 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 ); /* - * aff.Y = jac.Y / (jac.Z)^3 mod p + * Z = 1 */ - MPI_CHK( mpi_mul_mpi( &aff->Y, &jac->Y, &ZZi ) ); MOD_MUL( aff->Y ); - MPI_CHK( mpi_mul_mpi( &aff->Y, &aff->Y, &Zi ) ); MOD_MUL( aff->Y ); + MPI_CHK( mpi_lset( &pt->Z, 1 ) ); cleanup: @@ -573,14 +499,14 @@ cleanup: /* * Point doubling R = 2 P, Jacobian coordinates (GECC 3.21) */ -static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R, - const ecp_ptjac *P ) +static int ecp_double_jac( const ecp_group *grp, ecp_point *R, + const ecp_point *P ) { int ret; mpi T1, T2, T3, X, Y, Z; if( mpi_cmp_int( &P->Z, 0 ) == 0 ) - return( ecp_ptjac_set_zero( R ) ); + return( ecp_set_zero( R ) ); mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); @@ -625,9 +551,10 @@ cleanup: /* * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * The coordinates of Q must be normalized (= affine). */ -static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, - const ecp_ptjac *P, const ecp_point *Q ) +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; @@ -636,10 +563,16 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, * Trivial cases: P == 0 or Q == 0 */ if( mpi_cmp_int( &P->Z, 0 ) == 0 ) - return( ecp_aff_to_jac( R, Q ) ); + return( ecp_copy( R, Q ) ); - if( Q->is_zero ) - return( ecp_ptjac_copy( R, P ) ); + if( mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 ); mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); @@ -660,7 +593,7 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R, } else { - ret = ecp_ptjac_set_zero( R ); + ret = ecp_set_zero( R ); goto cleanup; } } @@ -691,24 +624,17 @@ cleanup: } /* - * Addition: R = P + Q, affine wrapper + * 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; - ecp_ptjac J; - ecp_ptjac_init( &J ); - - MPI_CHK( ecp_aff_to_jac( &J, P ) ); - MPI_CHK( ecp_add_mixed( grp, &J, &J, Q ) ); - MPI_CHK( ecp_jac_to_aff( grp, R, &J ) ); + MPI_CHK( ecp_add_mixed( grp, R, P, Q ) ); + MPI_CHK( ecp_normalize( grp, R ) ); cleanup: - - ecp_ptjac_free( &J ); - return( ret ); } @@ -720,7 +646,7 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, { int ret, cmp; size_t pos; - ecp_ptjac Q[2]; + ecp_point Q[2]; cmp = mpi_cmp_int( m, 0 ); @@ -731,29 +657,29 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, * The general method works only for m != 0 */ if( cmp == 0 ) { - ecp_set_zero( R ); - return( 0 ); + return( ecp_set_zero( R ) ); } - ecp_ptjac_init( &Q[0] ); ecp_ptjac_init( &Q[1] ); + ecp_point_init( &Q[0] ); ecp_point_init( &Q[1] ); - ecp_ptjac_set_zero( &Q[0] ); + MPI_CHK( ecp_set_zero( &Q[0] ) ); for( pos = mpi_msb( m ) - 1 ; ; pos-- ) { MPI_CHK( ecp_double_jac( grp, &Q[0], &Q[0] ) ); MPI_CHK( ecp_add_mixed( grp, &Q[1], &Q[0], P ) ); - MPI_CHK( ecp_ptjac_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); + MPI_CHK( ecp_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); if( pos == 0 ) break; } - MPI_CHK( ecp_jac_to_aff( grp, R, &Q[0] ) ); + MPI_CHK( ecp_copy( R, &Q[0] ) ); + MPI_CHK( ecp_normalize( grp, R ) ); cleanup: - ecp_ptjac_free( &Q[0] ); ecp_ptjac_free( &Q[1] ); + ecp_point_free( &Q[0] ); ecp_point_free( &Q[1] ); return( ret ); } diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index ff51a080e..c82d6e54c 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -31,7 +31,7 @@ ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c TEST_ASSERT( ecp_add( &grp, &C, &A, &B ) == 0 ); if( {c_zero} ) - TEST_ASSERT( C.is_zero ); + TEST_ASSERT( mpi_cmp_int( &C.Z, 0 ) == 0 ); else { TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 ); @@ -41,7 +41,7 @@ ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c TEST_ASSERT( ecp_add( &grp, &C, &B, &A ) == 0 ); if( {c_zero} ) - TEST_ASSERT( C.is_zero ); + TEST_ASSERT( mpi_cmp_int( &C.Z, 0 ) == 0 ); else { TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 ); @@ -72,7 +72,7 @@ ecp_small_mul:m:r_zero:x_r:y_r:ret TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == {ret} ); if( {r_zero} ) - TEST_ASSERT( R.is_zero ); + TEST_ASSERT( mpi_cmp_int( &R.Z, 0 ) == 0 ); else { TEST_ASSERT( mpi_cmp_int( &R.X, {x_r} ) == 0 ); From 9674fd0d5e0801465116285e30dc179bb7058b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 19 Nov 2012 21:23:27 +0100 Subject: [PATCH 33/76] Added ecp_sub() as a variant of ecp_add() --- include/polarssl/ecp.h | 14 +++++++ library/ecp.c | 62 ++++++++++++++++++++++++---- tests/suites/test_suite_ecp.data | 27 ++++++++++++ tests/suites/test_suite_ecp.function | 37 +++++++++++++++++ 4 files changed, 132 insertions(+), 8 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index cea403af1..f3e636eb0 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -200,6 +200,20 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ); 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 + */ +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 * diff --git a/library/ecp.c b/library/ecp.c index 1c614b56d..748cccb93 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -550,24 +550,44 @@ cleanup: } /* - * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) - * The coordinates of Q must be normalized (= affine). + * Addition or subtraction: R = P + Q or 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. + * + * If sign >= 0, perform addition, otherwise perform subtraction, + * taking advantage of the fact that, for Q != 0, we have + * -Q = (Q.X, -Q.Y, Q.Z) */ static int ecp_add_mixed( const ecp_group *grp, ecp_point *R, - const ecp_point *P, const ecp_point *Q ) + const ecp_point *P, const ecp_point *Q, + signed char sign ) { int ret; mpi T1, T2, T3, T4, X, Y, Z; /* * Trivial cases: P == 0 or Q == 0 + * (Check Q first, so that we know Q != 0 when we compute -Q.) */ - if( mpi_cmp_int( &P->Z, 0 ) == 0 ) - return( ecp_copy( R, Q ) ); - if( mpi_cmp_int( &Q->Z, 0 ) == 0 ) return( ecp_copy( R, P ) ); + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + ret = ecp_copy( R, Q ); + + /* + * -R.Y mod P = P - R.Y unless R.Y == 0 + */ + if( ret == 0 && sign < 0) + if( mpi_cmp_int( &R->Y, 0 ) != 0 ) + ret = mpi_sub_mpi( &R->Y, &grp->P, &R->Y ); + + return( ret ); + } + /* * Make sure Q coordinates are normalized */ @@ -581,6 +601,17 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_point *R, 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 ); + + /* + * For subtraction, -Q.Y should have been used instead of Q.Y, + * so we replace T2 by -T2, which is P - T2 mod P + */ + if( sign < 0 ) + { + MPI_CHK( mpi_sub_mpi( &T2, &grp->P, &T2 ) ); + MOD_SUB( 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 ); @@ -631,7 +662,22 @@ int ecp_add( const ecp_group *grp, ecp_point *R, { int ret; - MPI_CHK( ecp_add_mixed( grp, R, P, Q ) ); + MPI_CHK( ecp_add_mixed( grp, R, P, Q , 1 ) ); + MPI_CHK( ecp_normalize( 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; + + MPI_CHK( ecp_add_mixed( grp, R, P, Q, -1 ) ); MPI_CHK( ecp_normalize( grp, R ) ); cleanup: @@ -667,7 +713,7 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, for( pos = mpi_msb( m ) - 1 ; ; pos-- ) { MPI_CHK( ecp_double_jac( grp, &Q[0], &Q[0] ) ); - MPI_CHK( ecp_add_mixed( grp, &Q[1], &Q[0], P ) ); + MPI_CHK( ecp_add_mixed( grp, &Q[1], &Q[0], P, 1 ) ); MPI_CHK( ecp_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); if( pos == 0 ) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 816df7735..c0dd0189d 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -22,6 +22,33 @@ ecp_small_add:0:"37":"31":0:"37":"31":0:21:32 ECP small addition #8 ecp_small_add:0:"14":"11":0:"14":"11":0:27:30 +ECP small subtraction #1 +ecp_small_sub:1:"":"":1:"":"":1:0:0 + +ECP small subtraction #2 +ecp_small_sub:1:"":"":0:"14":"11":0:14:36 + +ECP small subtraction #3 +ecp_small_sub:1:"":"":0:"13":"00":0:13:00 + +ECP small subtraction #4 +ecp_small_sub:0:"13":"00":0:"13":"00":1:0:0 + +ECP small subtraction #5 +ecp_small_sub:0:"14":"11":0:"14":"11":1:0:0 + +ECP small subtraction #6 +ecp_small_sub:0:"13":"00":0:"37":"16":0:34:14 + +ECP small subtraction #7 +ecp_small_sub:0:"14":"11":0:"37":"16":0:45:07 + +ECP small subtraction #8 +ecp_small_sub:0:"37":"31":0:"37":"16":0:21:32 + +ECP small subtraction #9 +ecp_small_sub:0:"14":"11":0:"14":"36":0:27:30 + ECP small multiplication negative ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index c82d6e54c..f494f4e67 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -53,6 +53,43 @@ ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c } END_CASE +BEGIN_CASE +ecp_small_sub:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c +{ + ecp_group grp; + ecp_point A, B, C; + + ecp_group_init( &grp ); + ecp_point_init( &A ); ecp_point_init( &B ); ecp_point_init( &C ); + + TEST_ASSERT( ecp_group_read_string( &grp, 10, + "47", "4", "17", "42", "13" ) == 0 ); + + if( {a_zero} ) + ecp_set_zero( &A ); + else + TEST_ASSERT( ecp_point_read_string( &A, 10, {x_a}, {y_a} ) == 0 ); + + if( {b_zero} ) + ecp_set_zero( &B ); + else + TEST_ASSERT( ecp_point_read_string( &B, 10, {x_b}, {y_b} ) == 0 ); + + TEST_ASSERT( ecp_sub( &grp, &C, &A, &B ) == 0 ); + + if( {c_zero} ) + TEST_ASSERT( mpi_cmp_int( &C.Z, 0 ) == 0 ); + else + { + TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 ); + TEST_ASSERT( mpi_cmp_int( &C.Y, {y_c} ) == 0 ); + } + + ecp_group_free( &grp ); + ecp_point_free( &A ); ecp_point_free( &B ); ecp_point_free( &C ); +} +END_CASE + BEGIN_CASE ecp_small_mul:m:r_zero:x_r:y_r:ret { From b4a310b47261d6b4ee98d855631bdf07977755db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 13 Nov 2012 20:57:00 +0100 Subject: [PATCH 34/76] Added a selftest about SPA resistance --- library/ecp.c | 82 +++++++++++++++++++++++++++- programs/test/selftest.c | 6 ++ tests/suites/test_suite_ecp.data | 4 ++ tests/suites/test_suite_ecp.function | 7 +++ 4 files changed, 98 insertions(+), 1 deletion(-) diff --git a/library/ecp.c b/library/ecp.c index 748cccb93..05f642343 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -38,6 +38,14 @@ #include "polarssl/ecp.h" #include +#if defined(POLARSSL_SELF_TEST) +/* + * Counts of point addition and doubling operations. + * Used to test resistance of point multiplication to SPA/timing attacks. + */ +unsigned long add_count, dbl_count; +#endif + /* * Initialize (the components of) a point */ @@ -505,6 +513,10 @@ static int ecp_double_jac( const ecp_group *grp, ecp_point *R, int ret; mpi T1, T2, T3, X, Y, Z; +#if defined(POLARSSL_SELF_TEST) + dbl_count++; +#endif + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) return( ecp_set_zero( R ) ); @@ -567,6 +579,10 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_point *R, 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 * (Check Q first, so that we know Q != 0 when we compute -Q.) @@ -738,7 +754,71 @@ cleanup: */ int ecp_self_test( int verbose ) { - return( verbose++ ); + int ret; + size_t i; + ecp_group grp; + ecp_point R; + mpi m; + unsigned long add_c_prev, dbl_c_prev; + char *exponents[] = + { + "400000000000000000000000000000000000000000000000", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "555555555555555555555555555555555555555555555555", + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", + "000000000000000000000000000000000000000000000010", + }; + + ecp_group_init( &grp ); + ecp_point_init( &R ); + mpi_init( &m ); + + MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) ); + + if( verbose != 0 ) + printf( " ECP test #1 (SPA resistance): " ); + + add_count = 0; + dbl_count = 0; + MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) ); + MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + add_count = 0; + dbl_count = 0; + + MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) ); + MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G ) ); + + if( add_count != add_c_prev || dbl_count != dbl_c_prev ) + { + if( verbose != 0 ) + printf( "failed (%zu)\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + printf( "Unexpected error, return code = %08X\n", ret ); + + ecp_group_free( &grp ); + ecp_point_free( &R ); + mpi_free( &m ); + + if( verbose != 0 ) + printf( "\n" ); + + return( ret ); } #endif diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 8dddf3481..333e3a16d 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -50,6 +50,7 @@ #include "polarssl/x509.h" #include "polarssl/xtea.h" #include "polarssl/pbkdf2.h" +#include "polarssl/ecp.h" int main( int argc, char *argv[] ) { @@ -155,6 +156,11 @@ int main( int argc, char *argv[] ) return( ret ); #endif +#if defined(POLARSSL_ECP_C) + if( ( ret = ecp_self_test( v ) ) != 0 ) + return( ret ); +#endif + #else printf( " POLARSSL_SELF_TEST not defined.\n" ); #endif diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index c0dd0189d..71d5fad98 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -114,3 +114,7 @@ ecp_test_vect:SECP384R1:"D27335EA71664AF244DD14E9FD1260715DFD8A7965571C48D709EE7 ECP test vectors secp521r1 ecp_test_vect:SECP521R1:"0113F82DA825735E3D97276683B2B74277BAD27335EA71664AF2430CC4F33459B9669EE78B3FFB9B8683015D344DCBFEF6FB9AF4C6C470BE254516CD3C1A1FB47362":"01EBB34DD75721ABF8ADC9DBED17889CBB9765D90A7C60F2CEF007BB0F2B26E14881FD4442E689D61CB2DD046EE30E3FFD20F9A45BBDF6413D583A2DBF59924FD35C":"00F6B632D194C0388E22D8437E558C552AE195ADFD153F92D74908351B2F8C4EDA94EDB0916D1B53C020B5EECAED1A5FC38A233E4830587BB2EE3489B3B42A5A86A4":"00CEE3480D8645A17D249F2776D28BAE616952D1791FDB4B70F7C3378732AA1B22928448BCD1DC2496D435B01048066EBE4F72903C361B1A9DC1193DC2C9D0891B96":"010EBFAFC6E85E08D24BFFFCC1A4511DB0E634BEEB1B6DEC8C5939AE44766201AF6200430BA97C8AC6A0E9F08B33CE7E9FEEB5BA4EE5E0D81510C24295B8A08D0235":"00A4A6EC300DF9E257B0372B5E7ABFEF093436719A77887EBB0B18CF8099B9F4212B6E30A1419C18E029D36863CC9D448F4DBA4D2A0E60711BE572915FBD4FEF2695":"00CDEA89621CFA46B132F9E4CFE2261CDE2D4368EB5656634C7CC98C7A00CDE54ED1866A0DD3E6126C9D2F845DAFF82CEB1DA08F5D87521BB0EBECA77911169C20CC":"00F9A71641029B7FC1A808AD07CD4861E868614B865AFBECAB1F2BD4D8B55EBCB5E3A53143CEB2C511B1AE0AF5AC827F60F2FD872565AC5CA0A164038FE980A7E4BD" + +ECP selftest +depends_on:POLARSSL_SELF_TEST +ecp_selftest: diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index f494f4e67..389bc6e91 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -194,3 +194,10 @@ ecp_fast_mod:id:N ecp_group_free( &grp ); } END_CASE + +BEGIN_CASE +ecp_selftest: +{ + TEST_ASSERT( ecp_self_test( 0 ) == 0 ); +} +END_CASE From 855560758cfc8b844f4b4dbb69b56e6bfe8793dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 17 Nov 2012 19:54:20 +0100 Subject: [PATCH 35/76] Added function preparing for faster multiplication --- include/polarssl/ecp.h | 12 +++++ library/ecp.c | 115 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 1 deletion(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index f3e636eb0..15da5efad 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -97,6 +97,18 @@ ecp_group; #define POLARSSL_ECP_DP_SECP384R1 3 #define POLARSSL_ECP_DP_SECP521R1 4 +/* + * Maximum NAF width used for point multipliation. Default: 7. + * Minimum value: 2. Maximum value: 8. + * + * Result is an array of at most ( 1 << ( POLARSSL_ECP_NAF_WIDTH - 1 ) ) + * points used for point multiplication, so at most 64 by default. + * In practice, most curves will use less precomputed points. + * + * Reduction in size may reduce speed for big curves. + */ +#define POLARSSL_ECP_NAF_WIDTH 7 /**< Maximum NAF width used. */ + #ifdef __cplusplus extern "C" { #endif diff --git a/library/ecp.c b/library/ecp.c index 05f642343..c10ae23e6 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -700,6 +700,70 @@ cleanup: return( ret ); } +/* + * Compute a modified width-w non-adjacent form (NAF) of a number, + * with a fixed pattern for resistance to SPA/timing attacks, + * see . + * (The resulting multiplication algorithm can also been seen as a + * modification of 2^w-ary multiplication, with signed coefficients, + * all of them odd.) + * + * Input: + * m must be an odd positive mpi less than w * k bits long + * x must be an array of k elements + * w must be less than a certain maximum (currently 8) + * + * The result is a sequence x[0], ..., x[k-1] with x[i] in the range + * - 2^(width - 1) .. 2^(width - 1) - 1 such that + * m = (2 * x[0] + 1) + 2^width * (2 * x[1] + 1) + ... + * + 2^((k-1) * width) * (2 * x[k-1] + 1) + * + * Compared to "Algorithm SPA-resistant Width-w NAF with Odd Scalar" + * p. 335 of the cited reference, here we return only u, not d_w since + * it is known that the other d_w[j] will be 0. Moreover, the returned + * string doesn't actually store u_i but x_i = u_i / 2 since it is known + * that u_i is odd. Also, since we always select a positive value for d + * mod 2^w, we don't need to check the sign of u[i-1] when the reference + * does. Finally, there is an off-by-one error in the reference: the + * last index should be k-1, not k. + */ +static int ecp_w_naf_fixed( signed char x[], size_t k, unsigned char w, + const mpi *m ) +{ + int ret; + unsigned int i, u, mask, carry; + mpi M; + + mpi_init( &M ); + + MPI_CHK( mpi_copy( &M, m ) ); + mask = ( 1 << w ) - 1; + carry = 1 << ( w - 1 ); + + for( i = 0; i < k; i++ ) + { + u = M.p[0] & mask; + + if( ( u & 1 ) == 0 && i > 0 ) + x[i - 1] -= carry; + + x[i] = u >> 1; + mpi_shift_r( &M, w ); + } + + /* + * We should have consumed all the bits now + */ + if( mpi_cmp_int( &M, 0 ) != 0 ) + ret = POLARSSL_ERR_ECP_GENERIC; + +cleanup: + + mpi_free( &M ); + + return( ret ); +} + /* * Integer multiplication: R = m * P (GECC 5.7, SPA-resistant) */ @@ -756,6 +820,7 @@ int ecp_self_test( int verbose ) { int ret; size_t i; + int j, jj; ecp_group grp; ecp_point R; mpi m; @@ -766,13 +831,61 @@ int ecp_self_test( int verbose ) "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "555555555555555555555555555555555555555555555555", "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", - "000000000000000000000000000000000000000000000010", + /* "000000000000000000000000000000000000000000000010", TODO */ }; + signed char x[3]; ecp_group_init( &grp ); ecp_point_init( &R ); mpi_init( &m ); + if( verbose != 0 ) + printf( " ECP test #0 (naf): " ); + + for( j = 1; j < 32; j += 2 ) + { + mpi_lset( &m, j ); + + x[0] = x[1] = x[2] = 0; + MPI_CHK( ecp_w_naf_fixed( x, 3, 2, &m ) ); + jj = ( 2 * x[0] + 1 ) + 4 * ( 2 * x[1] + 1 ) + 16 * ( 2 * x[2] + 1 ); + + if( j != jj || + x[0] > 1 || x[0] < -2 || + x[1] > 1 || x[1] < -2 || + x[2] > 1 || x[2] < -2 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + printf( "%i != %i (%i, %i, %i)\n", j, jj, x[0], x[1], x[2] ); + + ret = 1; + goto cleanup; + } + + x[0] = x[1] = x[2] = 0; + MPI_CHK( ecp_w_naf_fixed( x, 2, 3, &m ) ); + jj = ( 2 * x[0] + 1 ) + 8 * ( 2 * x[1] + 1 ); + + if( j != jj || + x[0] > 3 || x[0] < -4 || + x[1] > 3 || x[1] < -4 || + x[2] != 0 ) + { + if( verbose != 0 ) + printf( "failed\n" ); + + printf( "%i != %i (%i, %i)\n", j, jj, x[0], x[1] ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + printf( "passed\n" ); + MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) ); if( verbose != 0 ) From 7652a593d690c63e2d121b6147679ef7bedcee15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 21 Nov 2012 10:00:45 +0100 Subject: [PATCH 36/76] Added a precompute() function for fast mult --- library/ecp.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index c10ae23e6..f7b5b19ee 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -727,8 +727,8 @@ cleanup: * does. Finally, there is an off-by-one error in the reference: the * last index should be k-1, not k. */ -static int ecp_w_naf_fixed( signed char x[], size_t k, unsigned char w, - const mpi *m ) +static int ecp_w_naf_fixed( signed char x[], size_t k, + unsigned char w, const mpi *m ) { int ret; unsigned int i, u, mask, carry; @@ -764,6 +764,36 @@ cleanup: return( ret ); } +/* + * Precompute odd multiples of P up to (2 * t_len - 1) P. + * The table is filled with T[i] = (2 * i + 1) P. + */ +static int ecp_precompute( ecp_point T[], size_t t_len, + const ecp_group *grp, const ecp_point *P ) +{ + int ret; + size_t i; + ecp_point PP; + + ecp_point_init( &PP ); + + MPI_CHK( ecp_add( grp, &PP, P, P ) ); + + MPI_CHK( ecp_copy( &T[0], P ) ); + + /* + * TODO: use Montgomery's trick for less inversions + */ + for( i = 1; i < t_len; i++ ) + MPI_CHK( ecp_add( grp, &T[i], &T[i-1], &PP ) ); + +cleanup: + + ecp_point_free( &PP ); + + return( ret ); +} + /* * Integer multiplication: R = m * P (GECC 5.7, SPA-resistant) */ From b63f9e98f52bdc4b0affe82c8516ed77e88e7853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 21 Nov 2012 13:00:58 +0100 Subject: [PATCH 37/76] Made ecp_mul() faster and truly SPA resistant --- include/polarssl/ecp.h | 18 +++- library/ecp.c | 171 +++++++++++++++++-------------- tests/suites/test_suite_ecp.data | 9 ++ 3 files changed, 119 insertions(+), 79 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 15da5efad..333655385 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -97,17 +97,23 @@ ecp_group; #define POLARSSL_ECP_DP_SECP384R1 3 #define POLARSSL_ECP_DP_SECP521R1 4 +/** + * Maximum bit size of the groups (that is, of N) + */ +#define POLARSSL_ECP_MAX_N_BITS 521 + /* - * Maximum NAF width used for point multipliation. Default: 7. + * Maximum window size (actually, NAF width) used for point multipliation. + * Default: 7. * Minimum value: 2. Maximum value: 8. * - * Result is an array of at most ( 1 << ( POLARSSL_ECP_NAF_WIDTH - 1 ) ) + * Result is an array of at most ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) ) * points used for point multiplication, so at most 64 by default. * In practice, most curves will use less precomputed points. * * Reduction in size may reduce speed for big curves. */ -#define POLARSSL_ECP_NAF_WIDTH 7 /**< Maximum NAF width used. */ +#define POLARSSL_ECP_WINDOW_SIZE 7 /**< Maximum NAF width used. */ #ifdef __cplusplus extern "C" { @@ -236,7 +242,11 @@ int ecp_sub( const ecp_group *grp, ecp_point *R, * * \return 0 if successful, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - * POLARSSL_ERR_ECP_GENERIC if m < 0 + * POLARSSL_ERR_ECP_GENERIC if m < 0 of m has greater bit + * length than N, the number of points in the group. + * + * \note This function executes a constant number of operations + * for random m in the allowed range. */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); diff --git a/library/ecp.c b/library/ecp.c index f7b5b19ee..0898e4d54 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -768,8 +768,9 @@ cleanup: * Precompute odd multiples of P up to (2 * t_len - 1) P. * The table is filled with T[i] = (2 * i + 1) P. */ -static int ecp_precompute( ecp_point T[], size_t t_len, - const ecp_group *grp, const ecp_point *P ) +static int ecp_precompute( const ecp_group *grp, + ecp_point T[], size_t t_len, + const ecp_point *P ) { int ret; size_t i; @@ -795,47 +796,114 @@ cleanup: } /* - * Integer multiplication: R = m * P (GECC 5.7, SPA-resistant) + * Maximum length of the precomputed table + */ +#define MAX_PRE_LEN ( 1 << (POLARSSL_ECP_WINDOW_SIZE - 1) ) + +/* + * Maximum length of the NAF: ceil( grp->nbits + 1 ) / w + * (that is: grp->nbits / w + 1) + * Allow p_bits + 1 bits in case M = grp->N + 1 is one bit longer than N. + */ +#define MAX_NAF_LEN ( POLARSSL_ECP_MAX_N_BITS / 2 + 1 ) + +/* + * Integer multiplication: R = m * P + * + * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed() + * and . + * + * This function executes a fixed number of operations for + * random m in the range 0 .. 2^nbits - 1. */ int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ) { - int ret, cmp; - size_t pos; - ecp_point Q[2]; + int ret; + unsigned char w, m_is_odd; + size_t pre_len, naf_len, i, j; + signed char naf[ MAX_NAF_LEN ]; + ecp_point Q, T[ MAX_PRE_LEN ]; + mpi M; - cmp = mpi_cmp_int( m, 0 ); - - if( cmp < 0 ) + if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits ) return( POLARSSL_ERR_ECP_GENERIC ); + w = 3; // TODO: find optimal values once precompute() is optimized + + if( w < 2 ) + w = 2; + if( w > POLARSSL_ECP_WINDOW_SIZE ) + w = POLARSSL_ECP_WINDOW_SIZE; + + pre_len = 1 << ( w - 1 ); + naf_len = grp->nbits / w + 1; + + mpi_init( &M ); + ecp_point_init( &Q ); + for( i = 0; i < pre_len; i++ ) + ecp_point_init( &T[i] ); + + m_is_odd = ( mpi_get_bit( m, 0 ) == 1 ); + /* - * The general method works only for m != 0 + * Make sure M is odd: + * later we'll get m * P by subtracting * P or 2 * P to M * P. */ - if( cmp == 0 ) { - return( ecp_set_zero( R ) ); - } + MPI_CHK( mpi_copy( &M, m ) ); + MPI_CHK( mpi_add_int( &M, &M, 1 + m_is_odd ) ); - ecp_point_init( &Q[0] ); ecp_point_init( &Q[1] ); + /* + * Compute the fixed-pattern NAF and precompute odd multiples + */ + MPI_CHK( ecp_w_naf_fixed( naf, naf_len, w, &M ) ); + MPI_CHK( ecp_precompute( grp, T, pre_len, P ) ); - MPI_CHK( ecp_set_zero( &Q[0] ) ); - - for( pos = mpi_msb( m ) - 1 ; ; pos-- ) + /* + * Compute M * P, using a variant of left-to-right 2^w-ary multiplication: + * at each step we add (2 * naf[i] + 1) P, then multiply by 2^w. + * + * If naf[i] >= 0, we have (2 * naf[i] + 1) P == T[ naf[i] ] + * Otherwise, (2 * naf[i] + 1) P == - ( 2 * ( - naf[i] - 1 ) + 1) P + * == T[ - naf[i] - 1 ] + */ + MPI_CHK( ecp_set_zero( &Q ) ); + i = naf_len - 1; + while( 1 ) { - MPI_CHK( ecp_double_jac( grp, &Q[0], &Q[0] ) ); - MPI_CHK( ecp_add_mixed( grp, &Q[1], &Q[0], P, 1 ) ); - MPI_CHK( ecp_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) ); + if( naf[i] < 0 ) + { + MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ - naf[i] - 1 ], -1 ) ); + } + else + { + MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ naf[i] ], +1 ) ); + } - if( pos == 0 ) + if( i == 0 ) break; + i--; + + for( j = 0; j < w; j++ ) + { + MPI_CHK( ecp_double_jac( grp, &Q, &Q ) ); + } } - MPI_CHK( ecp_copy( R, &Q[0] ) ); - MPI_CHK( ecp_normalize( grp, R ) ); + /* + * Now get m * P from M * P. + * Since we don't need T[] any more, we can recycle it: + * we already have T[0] = P, now set T[1] = 2 * P. + */ + MPI_CHK( ecp_add( grp, &T[1], P, P ) ); + MPI_CHK( ecp_sub( grp, R, &Q, &T[m_is_odd] ) ); cleanup: - ecp_point_free( &Q[0] ); ecp_point_free( &Q[1] ); + mpi_free( &M ); + ecp_point_free( &Q ); + for( i = 0; i < pre_len; i++ ) + ecp_point_free( &T[i] ); return( ret ); } @@ -850,72 +918,25 @@ int ecp_self_test( int verbose ) { int ret; size_t i; - int j, jj; ecp_group grp; ecp_point R; mpi m; unsigned long add_c_prev, dbl_c_prev; char *exponents[] = { + "000000000000000000000000000000000000000000000000", /* zero */ + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* N */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ "400000000000000000000000000000000000000000000000", "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "555555555555555555555555555555555555555555555555", - "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", - /* "000000000000000000000000000000000000000000000010", TODO */ }; - signed char x[3]; ecp_group_init( &grp ); ecp_point_init( &R ); mpi_init( &m ); - if( verbose != 0 ) - printf( " ECP test #0 (naf): " ); - - for( j = 1; j < 32; j += 2 ) - { - mpi_lset( &m, j ); - - x[0] = x[1] = x[2] = 0; - MPI_CHK( ecp_w_naf_fixed( x, 3, 2, &m ) ); - jj = ( 2 * x[0] + 1 ) + 4 * ( 2 * x[1] + 1 ) + 16 * ( 2 * x[2] + 1 ); - - if( j != jj || - x[0] > 1 || x[0] < -2 || - x[1] > 1 || x[1] < -2 || - x[2] > 1 || x[2] < -2 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - printf( "%i != %i (%i, %i, %i)\n", j, jj, x[0], x[1], x[2] ); - - ret = 1; - goto cleanup; - } - - x[0] = x[1] = x[2] = 0; - MPI_CHK( ecp_w_naf_fixed( x, 2, 3, &m ) ); - jj = ( 2 * x[0] + 1 ) + 8 * ( 2 * x[1] + 1 ); - - if( j != jj || - x[0] > 3 || x[0] < -4 || - x[1] > 3 || x[1] < -4 || - x[2] != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - printf( "%i != %i (%i, %i)\n", j, jj, x[0], x[1] ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) ); if( verbose != 0 ) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 71d5fad98..0abdabf42 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -94,6 +94,15 @@ ecp_small_mul:12:0:17:05:0 ECP small multiplication #13 ecp_small_mul:13:1:0:0:0 +ECP small multiplication #14 +ecp_small_mul:1:0:17:42:0 + +ECP small multiplication #15 +ecp_small_mul:2:0:20:01:0 + +ECP small multiplication too big +ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" From cdd44324e9b8954e8a9d5719a0827ad0d2db8fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 21 Nov 2012 16:00:55 +0100 Subject: [PATCH 38/76] Added ecp_normalize_many() for faster precompute() --- library/ecp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 0898e4d54..802f532f1 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -37,6 +37,7 @@ #include "polarssl/ecp.h" #include +#include #if defined(POLARSSL_SELF_TEST) /* @@ -472,12 +473,12 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) static int ecp_normalize( const ecp_group *grp, ecp_point *pt ) { int ret; - mpi Zi, ZZi, T; + mpi Zi, ZZi; if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) return( 0 ); - mpi_init( &Zi ); mpi_init( &ZZi ); mpi_init( &T ); + mpi_init( &Zi ); mpi_init( &ZZi ); /* * X = X / Z^2 mod p @@ -499,11 +500,90 @@ static int ecp_normalize( const ecp_group *grp, ecp_point *pt ) cleanup: - mpi_free( &Zi ); mpi_free( &ZZi ); mpi_free( &T ); + mpi_free( &Zi ); mpi_free( &ZZi ); return( ret ); } +/* + * Normalize jacobian coordinates of an array of points, + * using Montgomery's trick to perform only one division. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * FIXME: assumes all points are non zero + */ +static int ecp_normalize_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( grp, T ) ); + + if( ( c = (mpi *) malloc( t_len * sizeof( mpi ) ) ) == NULL ) + return( POLARSSL_ERR_ECP_GENERIC ); + + 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 ); + MPI_CHK( mpi_lset( &T[i].Z, 1 ) ); + + 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] ); + free( c ); + + return( ret ); +} + + /* * Point doubling R = 2 P, Jacobian coordinates (GECC 3.21) */ @@ -782,11 +862,13 @@ static int ecp_precompute( const ecp_group *grp, MPI_CHK( ecp_copy( &T[0], P ) ); - /* - * TODO: use Montgomery's trick for less inversions - */ for( i = 1; i < t_len; i++ ) - MPI_CHK( ecp_add( grp, &T[i], &T[i-1], &PP ) ); + MPI_CHK( ecp_add_mixed( grp, &T[i], &T[i-1], &PP, +1 ) ); + + /* + * T[0] = P already has normalized coordinates + */ + ecp_normalize_many( grp, T + 1, t_len - 1 ); cleanup: @@ -829,7 +911,7 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits ) return( POLARSSL_ERR_ECP_GENERIC ); - w = 3; // TODO: find optimal values once precompute() is optimized + w = 5; // TODO: find optimal values once precompute() is optimized if( w < 2 ) w = 2; From 3680c82c5ae1d651ddc9ad12baf4e5ff5df5211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 21 Nov 2012 18:49:45 +0100 Subject: [PATCH 39/76] Made choice of w safer and more optimal --- library/ecp.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 802f532f1..3bef06c15 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -507,11 +507,12 @@ cleanup: /* * Normalize jacobian coordinates of an array of points, - * using Montgomery's trick to perform only one division. + * 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.) * - * FIXME: assumes all points are non zero + * Warning: fails if one of the points is zero! + * This should never happen, see choice of w in ecp_mul(). */ static int ecp_normalize_many( const ecp_group *grp, ecp_point T[], size_t t_len ) @@ -868,7 +869,7 @@ static int ecp_precompute( const ecp_group *grp, /* * T[0] = P already has normalized coordinates */ - ecp_normalize_many( grp, T + 1, t_len - 1 ); + MPI_CHK( ecp_normalize_many( grp, T + 1, t_len - 1 ) ); cleanup: @@ -911,12 +912,20 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits ) return( POLARSSL_ERR_ECP_GENERIC ); - w = 5; // TODO: find optimal values once precompute() is optimized + w = grp->nbits >= 521 ? 6 : + grp->nbits >= 224 ? 5 : + 4; - if( w < 2 ) - w = 2; + /* + * Make sure w is within the limits. + * The last test ensures that none of the precomputed points is zero, + * which wouldn't be handled correctly by ecp_normalize_many(). + * It is only useful for small curves, as used in the test suite. + */ if( w > POLARSSL_ECP_WINDOW_SIZE ) w = POLARSSL_ECP_WINDOW_SIZE; + if( w < 2 || w >= grp->nbits ) + w = 2; pre_len = 1 << ( w - 1 ); naf_len = grp->nbits / w + 1; @@ -980,6 +989,7 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, MPI_CHK( ecp_add( grp, &T[1], P, P ) ); MPI_CHK( ecp_sub( grp, R, &Q, &T[m_is_odd] ) ); + cleanup: mpi_free( &M ); From c554e9acf1f3054f41b4145976edc36eb8ad70c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 21 Nov 2012 19:20:04 +0100 Subject: [PATCH 40/76] Added test vectors from RFC 5903 --- tests/suites/test_suite_ecp.data | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 0abdabf42..c8e76b29d 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -109,21 +109,30 @@ ecp_fast_mod:SECP192R1:"00000000000001050000000000000104000000000000010300000000 ECP mod p192 random ecp_fast_mod:SECP192R1:"36CF96B45D706A0954D89E52CE5F38517A2270E0175849B6F3740151D238CCABEF921437E475881D83BB69E4AA258EBD" -ECP test vectors secp192r1 +ECP test vectors secp192r1 rfc 5114 ecp_test_vect:SECP192R1:"323FA3169D8E9C6593F59476BC142000AB5BE0E249C43426":"CD46489ECFD6C105E7B3D32566E2B122E249ABAADD870612":"68887B4877DF51DD4DC3D6FD11F0A26F8FD3844317916E9A":"631F95BB4A67632C9C476EEE9AB695AB240A0499307FCF62":"519A121680E0045466BA21DF2EEE47F5973B500577EF13D5":"FF613AB4D64CEE3A20875BDB10F953F6B30CA072C60AA57F":"AD420182633F8526BFE954ACDA376F05E5FF4F837F54FEBE":"4371545ED772A59741D0EDA32C671112B7FDDD51461FCF32" -ECP test vectors secp224r1 +ECP test vectors secp224r1 rfc 5114 ecp_test_vect:SECP224R1:"B558EB6C288DA707BBB4F8FBAE2AB9E9CB62E3BC5C7573E22E26D37F":"49DFEF309F81488C304CFF5AB3EE5A2154367DC7833150E0A51F3EEB":"4F2B5EE45762C4F654C1A0C67F54CF88B016B51BCE3D7C228D57ADB4":"AC3B1ADD3D9770E6F6A708EE9F3B8E0AB3B480E9F27F85C88B5E6D18":"6B3AC96A8D0CDE6A5599BE8032EDF10C162D0A8AD219506DCD42A207":"D491BE99C213A7D1CA3706DEBFE305F361AFCBB33E2609C8B1618AD5":"52272F50F46F4EDC9151569092F46DF2D96ECC3B6DC1714A4EA949FA":"5F30C6AA36DDC403C0ACB712BB88F1763C3046F6D919BD9C524322BF" -ECP test vectors secp256r1 +ECP test vectors secp256r1 rfc 5114 ecp_test_vect:SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"B120DE4AA36492795346E8DE6C2C8646AE06AAEA279FA775B3AB0715F6CE51B0":"9F1B7EECE20D7B5ED8EC685FA3F071D83727027092A8411385C34DDE5708B2B6":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50" -ECP test vectors secp384r1 +ECP test vectors secp384r1 rfc 5114 ecp_test_vect:SECP384R1:"D27335EA71664AF244DD14E9FD1260715DFD8A7965571C48D709EE7A7962A156D706A90CBCB5DF2986F05FEADB9376F1":"793148F1787634D5DA4C6D9074417D05E057AB62F82054D10EE6B0403D6279547E6A8EA9D1FD77427D016FE27A8B8C66":"C6C41294331D23E6F480F4FB4CD40504C947392E94F4C3F06B8F398BB29E42368F7A685923DE3B67BACED214A1A1D128":"52D1791FDB4B70F89C0F00D456C2F7023B6125262C36A7DF1F80231121CCE3D39BE52E00C194A4132C4A6C768BCD94D2":"5CD42AB9C41B5347F74B8D4EFB708B3D5B36DB65915359B44ABC17647B6B9999789D72A84865AE2F223F12B5A1ABC120":"E171458FEAA939AAA3A8BFAC46B404BD8F6D5B348C0FA4D80CECA16356CA933240BDE8723415A8ECE035B0EDF36755DE":"5EA1FC4AF7256D2055981B110575E0A8CAE53160137D904C59D926EB1B8456E427AA8A4540884C37DE159A58028ABC0E":"0CC59E4B046414A81C8A3BDFDCA92526C48769DD8D3127CAA99B3632D1913942DE362EAFAA962379374D9F3F066841CA" -ECP test vectors secp521r1 +ECP test vectors secp521r1 rfc 5114 ecp_test_vect:SECP521R1:"0113F82DA825735E3D97276683B2B74277BAD27335EA71664AF2430CC4F33459B9669EE78B3FFB9B8683015D344DCBFEF6FB9AF4C6C470BE254516CD3C1A1FB47362":"01EBB34DD75721ABF8ADC9DBED17889CBB9765D90A7C60F2CEF007BB0F2B26E14881FD4442E689D61CB2DD046EE30E3FFD20F9A45BBDF6413D583A2DBF59924FD35C":"00F6B632D194C0388E22D8437E558C552AE195ADFD153F92D74908351B2F8C4EDA94EDB0916D1B53C020B5EECAED1A5FC38A233E4830587BB2EE3489B3B42A5A86A4":"00CEE3480D8645A17D249F2776D28BAE616952D1791FDB4B70F7C3378732AA1B22928448BCD1DC2496D435B01048066EBE4F72903C361B1A9DC1193DC2C9D0891B96":"010EBFAFC6E85E08D24BFFFCC1A4511DB0E634BEEB1B6DEC8C5939AE44766201AF6200430BA97C8AC6A0E9F08B33CE7E9FEEB5BA4EE5E0D81510C24295B8A08D0235":"00A4A6EC300DF9E257B0372B5E7ABFEF093436719A77887EBB0B18CF8099B9F4212B6E30A1419C18E029D36863CC9D448F4DBA4D2A0E60711BE572915FBD4FEF2695":"00CDEA89621CFA46B132F9E4CFE2261CDE2D4368EB5656634C7CC98C7A00CDE54ED1866A0DD3E6126C9D2F845DAFF82CEB1DA08F5D87521BB0EBECA77911169C20CC":"00F9A71641029B7FC1A808AD07CD4861E868614B865AFBECAB1F2BD4D8B55EBCB5E3A53143CEB2C511B1AE0AF5AC827F60F2FD872565AC5CA0A164038FE980A7E4BD" +ECP test vectors secp256r1 rfc 5903 +ecp_test_vect:SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"DAD0B65394221CF9B051E1FECA5787D098DFE637FC90B9EF945D0C3772581180":"5271A0461CDB8252D61F1C456FA3E59AB1F45B33ACCF5F58389E0577B8990BB3":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D12DFB5289C8D4F81208B70270398C342296970A0BCCB74C736FC7554494BF63":"56FBF3CA366CC23E8157854C13C58D6AAC23F046ADA30F8353E74F33039872AB":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":"522BDE0AF0D8585B8DEF9C183B5AE38F50235206A8674ECB5D98EDB20EB153A2" + +ECP test vectors secp384r1 rfc 5903 +ecp_test_vect:SECP384R1:"099F3C7034D4A2C699884D73A375A67F7624EF7C6B3C0F160647B67414DCE655E35B538041E649EE3FAEF896783AB194":"667842D7D180AC2CDE6F74F37551F55755C7645C20EF73E31634FE72B4C55EE6DE3AC808ACB4BDB4C88732AEE95F41AA":"9482ED1FC0EEB9CAFC4984625CCFC23F65032149E0E144ADA024181535A0F38EEB9FCFF3C2C947DAE69B4C634573A81C":"41CB0779B4BDB85D47846725FBEC3C9430FAB46CC8DC5060855CC9BDA0AA2942E0308312916B8ED2960E4BD55A7448FC":"E558DBEF53EECDE3D3FCCFC1AEA08A89A987475D12FD950D83CFA41732BC509D0D1AC43A0336DEF96FDA41D0774A3571":"DCFBEC7AACF3196472169E838430367F66EEBE3C6E70C416DD5F0C68759DD1FFF83FA40142209DFF5EAAD96DB9E6386C":"11187331C279962D93D604243FD592CB9D0A926F422E47187521287E7156C5C4D603135569B9E9D09CF5D4A270F59746":"A2A9F38EF5CAFBE2347CF7EC24BDD5E624BC93BFA82771F40D1B65D06256A852C983135D4669F8792F2C1D55718AFBB4" + +ECP test vectors secp521r1 rfc 5903 +ecp_test_vect:SECP521R1:"0037ADE9319A89F4DABDB3EF411AACCCA5123C61ACAB57B5393DCE47608172A095AA85A30FE1C2952C6771D937BA9777F5957B2639BAB072462F68C27A57382D4A52":"0015417E84DBF28C0AD3C278713349DC7DF153C897A1891BD98BAB4357C9ECBEE1E3BF42E00B8E380AEAE57C2D107564941885942AF5A7F4601723C4195D176CED3E":"017CAE20B6641D2EEB695786D8C946146239D099E18E1D5A514C739D7CB4A10AD8A788015AC405D7799DC75E7B7D5B6CF2261A6A7F1507438BF01BEB6CA3926F9582":"0145BA99A847AF43793FDD0E872E7CDFA16BE30FDC780F97BCCC3F078380201E9C677D600B343757A3BDBF2A3163E4C2F869CCA7458AA4A4EFFC311F5CB151685EB9":"00D0B3975AC4B799F5BEA16D5E13E9AF971D5E9B984C9F39728B5E5739735A219B97C356436ADC6E95BB0352F6BE64A6C2912D4EF2D0433CED2B6171640012D9460F":"015C68226383956E3BD066E797B623C27CE0EAC2F551A10C2C724D9852077B87220B6536C5C408A1D2AEBB8E86D678AE49CB57091F4732296579AB44FCD17F0FC56A":"01144C7D79AE6956BC8EDB8E7C787C4521CB086FA64407F97894E5E6B2D79B04D1427E73CA4BAA240A34786859810C06B3C715A3A8CC3151F2BEE417996D19F3DDEA":"01B901E6B17DB2947AC017D853EF1C1674E5CFE59CDA18D078E05D1B5242ADAA9FFC3C63EA05EDB1E13CE5B3A8E50C3EB622E8DA1B38E0BDD1F88569D6C99BAFFA43" + ECP selftest depends_on:POLARSSL_SELF_TEST ecp_selftest: From 1c33057a6345ee580a2630eec3b26e0e5b5764b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 24 Nov 2012 12:05:44 +0100 Subject: [PATCH 41/76] Added ecp_check_pubkey(). --- include/polarssl/ecp.h | 19 ++++++++++++ library/ecp.c | 45 ++++++++++++++++++++++++++++ tests/suites/test_suite_ecp.data | 30 +++++++++++++++++++ tests/suites/test_suite_ecp.function | 29 ++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 333655385..96c135b56 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -158,6 +158,25 @@ int ecp_set_zero( ecp_point *pt ); */ int ecp_copy( ecp_point *P, const ecp_point *Q ); +/** + * \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_GENERIC 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. + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ); + /** * \brief Import a non-zero point from two ASCII strings * diff --git a/library/ecp.c b/library/ecp.c index 3bef06c15..40732885c 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -467,6 +467,51 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) while( mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) ) +/* + * Check that a point is valid as a public key (SEC1 3.2.3.1) + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ) +{ + int ret; + mpi YY, RHS; + + if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + /* + * pt coordinates must be normalized for our checks + */ + if( mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + 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_GENERIC ); + + mpi_init( &YY ); mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 - 3) + B = X^3 - 3X + 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 ); + MPI_CHK( mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( 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_GENERIC; + +cleanup: + + mpi_free( &YY ); mpi_free( &RHS ); + + return( ret ); +} + /* * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) */ diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index c8e76b29d..15f90945d 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -103,6 +103,36 @@ ecp_small_mul:2:0:20:01:0 ECP small multiplication too big ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC +ECP small check pubkey #1 +ecp_small_check_pub:1:1:0:POLARSSL_ERR_ECP_GENERIC + +ECP small check pubkey #2 +ecp_small_check_pub:9:-1:1:POLARSSL_ERR_ECP_GENERIC + +ECP small check pubkey #3 +ecp_small_check_pub:9:46:1:0 + +ECP small check pubkey #4 +ecp_small_check_pub:13:47:1:POLARSSL_ERR_ECP_GENERIC + +ECP small check pubkey #5 +ecp_small_check_pub:13:0:1:0 + +ECP small check pubkey #6 +ecp_small_check_pub:-1:10:1:POLARSSL_ERR_ECP_GENERIC + +ECP small check pubkey #7 +ecp_small_check_pub:46:10:1:0 + +ECP small check pubkey #8 +ecp_small_check_pub:47:2:1:POLARSSL_ERR_ECP_GENERIC + +ECP small check pubkey #9 +ecp_small_check_pub:0:2:1:0 + +ECP small check pubkey #10 +ecp_small_check_pub:10:25:1:POLARSSL_ERR_ECP_GENERIC + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 389bc6e91..0fcc842da 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -122,6 +122,29 @@ ecp_small_mul:m:r_zero:x_r:y_r:ret } END_CASE +BEGIN_CASE +ecp_small_check_pub:x:y:z:ret +{ + ecp_group grp; + ecp_point P; + + ecp_group_init( &grp ); + ecp_point_init( &P ); + + TEST_ASSERT( ecp_group_read_string( &grp, 10, + "47", "4", "17", "42", "13" ) == 0 ); + + TEST_ASSERT( mpi_lset( &P.X, {x} ) == 0 ); + TEST_ASSERT( mpi_lset( &P.Y, {y} ) == 0 ); + TEST_ASSERT( mpi_lset( &P.Z, {z} ) == 0 ); + + TEST_ASSERT( ecp_check_pubkey( &grp, &P ) == {ret} ); + + ecp_group_free( &grp ); + ecp_point_free( &P ); +} +END_CASE + BEGIN_CASE ecp_test_vect:id:dA:xA:yA:dB:xB:yB:xZ:yZ { @@ -135,6 +158,8 @@ ecp_test_vect:id:dA:xA:yA:dB:xB:yB:xZ:yZ TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + TEST_ASSERT( ecp_check_pubkey( &grp, &grp.G ) == 0 ); + TEST_ASSERT( mpi_read_string( &dA, 16, {dA} ) == 0 ); TEST_ASSERT( mpi_read_string( &xA, 16, {xA} ) == 0 ); TEST_ASSERT( mpi_read_string( &yA, 16, {yA} ) == 0 ); @@ -147,16 +172,20 @@ ecp_test_vect:id:dA:xA:yA:dB:xB:yB:xZ:yZ TEST_ASSERT( ecp_mul( &grp, &R, &dA, &grp.G ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.X, &xA ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yA ) == 0 ); + TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 ); TEST_ASSERT( ecp_mul( &grp, &R, &dB, &R ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 ); + TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 ); TEST_ASSERT( ecp_mul( &grp, &R, &dB, &grp.G ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.X, &xB ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yB ) == 0 ); + TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 ); TEST_ASSERT( ecp_mul( &grp, &R, &dA, &R ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 ); + TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 ); ecp_group_free( &grp ); ecp_point_free( &R ); mpi_free( &dA ); mpi_free( &xA ); mpi_free( &yA ); mpi_free( &dB ); From e19feb5b461e5a718bf653bf6b820d042cd2ab58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 24 Nov 2012 14:10:14 +0100 Subject: [PATCH 42/76] Added ecp_write_binary(). --- include/polarssl/ecp.h | 14 +++++++++++ library/ecp.c | 37 ++++++++++++++++++++++++++++ tests/suites/test_suite_ecp.data | 12 +++++++++ tests/suites/test_suite_ecp.function | 33 +++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 96c135b56..a875d7ec8 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -209,6 +209,20 @@ 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 Export a point into unsigned binary data, uncompressed + * + * \param grp Group the point belongs to + * \param P Point to export + * \param olen Length of the actual ouput + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, or POLARSSL_ERR_ECP_GENERIC + */ +int ecp_write_binary( const ecp_group *grp, const ecp_point *P, + size_t *olen, unsigned char *buf, size_t buflen ); + /** * \brief Set a group using well-known domain parameters * diff --git a/library/ecp.c b/library/ecp.c index 40732885c..854da58c8 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -173,6 +173,43 @@ cleanup: return( ret ); } +/* + * Export a point into unsigned binary data, uncompressed format (SEC1 2.3.3) + */ +int ecp_write_binary( const ecp_group *grp, const ecp_point *P, + size_t *olen, unsigned char *buf, size_t buflen ) +{ + int ret; + size_t plen; + + /* + * Case P == 0 + */ + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mpi_size( &grp->P ); + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_GENERIC ); + + buf[0] = 0x04; + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + +cleanup: + return( ret ); +} + /* * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi. * See the documentation of struct ecp_group. diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 15f90945d..20ae3cd68 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -133,6 +133,18 @@ ecp_small_check_pub:0:2:1:0 ECP small check pubkey #10 ecp_small_check_pub:10:25:1:POLARSSL_ERR_ECP_GENERIC +ECP write binary #1 (zero, buffer just fits) +ecp_write_binary:SECP192R1:"01":"01":"00":"00":1:0 + +ECP write binary #2 (zero, buffer too small) +ecp_write_binary:SECP192R1:"01":"01":"00":"00":0:POLARSSL_ERR_ECP_GENERIC + +ECP write binary #3 (non-zero, buffer just fits) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":49:0 + +ECP write binary #4 (non-zero, buffer too small) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":48:POLARSSL_ERR_ECP_GENERIC + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 0fcc842da..1e50499b8 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -224,6 +224,39 @@ ecp_fast_mod:id:N } END_CASE +BEGIN_CASE +ecp_write_binary:id:x:y:z:out:blen:ret +{ + ecp_group grp; + ecp_point P; + unsigned char buf[256], str[512]; + size_t olen; + + memset( buf, 0, sizeof( buf ) ); + memset( str, 0, sizeof( str ) ); + + ecp_group_init( &grp ); ecp_point_init( &P ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( mpi_read_string( &P.X, 16, {x} ) == 0 ); + TEST_ASSERT( mpi_read_string( &P.Y, 16, {y} ) == 0 ); + TEST_ASSERT( mpi_read_string( &P.Z, 16, {z} ) == 0 ); + + TEST_ASSERT( ecp_write_binary( &grp, &P, &olen, buf, {blen} ) == {ret} ); + + if( {ret} == 0 ) + { + TEST_ASSERT( olen == strlen({out}) / 2 ); + + hexify( str, buf, {blen} ); + TEST_ASSERT( strcasecmp( (char *) str, {out} ) == 0 ); + } + + ecp_group_free( &grp ); ecp_point_free( &P ); +} +END_CASE + BEGIN_CASE ecp_selftest: { From 37d218a8e3e5b076d3fc4293f1437baf3df62940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 24 Nov 2012 15:19:55 +0100 Subject: [PATCH 43/76] Added support for writing points compressed --- include/polarssl/ecp.h | 11 +++++++-- library/ecp.c | 36 +++++++++++++++++++++------- tests/suites/test_suite_ecp.data | 32 +++++++++++++++++++------ tests/suites/test_suite_ecp.function | 10 ++++---- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index a875d7ec8..cd4dd9b27 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -115,6 +115,12 @@ ecp_group; */ #define POLARSSL_ECP_WINDOW_SIZE 7 /**< Maximum NAF width used. */ +/* + * Point formats + */ +#define POLARSSL_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define POLARSSL_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + #ifdef __cplusplus extern "C" { #endif @@ -210,17 +216,18 @@ int ecp_group_read_string( ecp_group *grp, int radix, const char *gx, const char *gy, const char *n); /** - * \brief Export a point into unsigned binary data, uncompressed + * \brief Export a point into unsigned binary data * * \param grp Group the point belongs to * \param P Point to export + * \param format Point format, should be a POLARSSL_ECP_PF_XXX macro * \param olen Length of the actual ouput * \param buf Output buffer * \param buflen Length of the output buffer * * \return 0 if successful, or POLARSSL_ERR_ECP_GENERIC */ -int ecp_write_binary( const ecp_group *grp, const ecp_point *P, +int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen ); /** diff --git a/library/ecp.c b/library/ecp.c index 854da58c8..6501fbe9f 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -174,16 +174,20 @@ cleanup: } /* - * Export a point into unsigned binary data, uncompressed format (SEC1 2.3.3) + * Export a point into unsigned binary data (SEC1 2.3.3) */ -int ecp_write_binary( const ecp_group *grp, const ecp_point *P, +int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen ) { int ret; size_t plen; + if( format != POLARSSL_ECP_PF_UNCOMPRESSED && + format != POLARSSL_ECP_PF_COMPRESSED ) + return( POLARSSL_ERR_ECP_GENERIC ); + /* - * Case P == 0 + * Common case: P == 0 */ if( mpi_cmp_int( &P->Z, 0 ) == 0 ) { @@ -197,14 +201,28 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, } plen = mpi_size( &grp->P ); - *olen = 2 * plen + 1; - if( buflen < *olen ) - return( POLARSSL_ERR_ECP_GENERIC ); + if( format == POLARSSL_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; - buf[0] = 0x04; - MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); - MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_GENERIC ); + + 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_GENERIC ); + + buf[0] = 0x02 + mpi_get_bit( &P->Y, 0 ); + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + } cleanup: return( ret ); diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 20ae3cd68..e84ac045e 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -133,17 +133,35 @@ ecp_small_check_pub:0:2:1:0 ECP small check pubkey #10 ecp_small_check_pub:10:25:1:POLARSSL_ERR_ECP_GENERIC -ECP write binary #1 (zero, buffer just fits) -ecp_write_binary:SECP192R1:"01":"01":"00":"00":1:0 +ECP write binary #0 (zero, bad format) +ecp_write_binary:SECP192R1:"01":"01":"00":UNKNOWN:"00":1:POLARSSL_ERR_ECP_GENERIC + +ECP write binary #1 (zero, uncompressed, buffer just fits) +ecp_write_binary:SECP192R1:"01":"01":"00":UNCOMPRESSED:"00":1:0 ECP write binary #2 (zero, buffer too small) -ecp_write_binary:SECP192R1:"01":"01":"00":"00":0:POLARSSL_ERR_ECP_GENERIC +ecp_write_binary:SECP192R1:"01":"01":"00":UNCOMPRESSED:"00":0:POLARSSL_ERR_ECP_GENERIC -ECP write binary #3 (non-zero, buffer just fits) -ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":49:0 +ECP write binary #3 (non-zero, uncompressed, buffer just fits) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":UNCOMPRESSED:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":49:0 -ECP write binary #4 (non-zero, buffer too small) -ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":48:POLARSSL_ERR_ECP_GENERIC +ECP write binary #4 (non-zero, uncompressed, buffer too small) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":UNCOMPRESSED:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":48:POLARSSL_ERR_ECP_GENERIC + +ECP write binary #5 (zero, compressed, buffer just fits) +ecp_write_binary:SECP192R1:"01":"01":"00":COMPRESSED:"00":1:0 + +ECP write binary #6 (zero, buffer too small) +ecp_write_binary:SECP192R1:"01":"01":"00":COMPRESSED:"00":0:POLARSSL_ERR_ECP_GENERIC + +ECP write binary #7 (even, compressed, buffer just fits) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":COMPRESSED:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0 + +ECP write binary #8 (even, compressed, buffer too small) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":COMPRESSED:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":24:POLARSSL_ERR_ECP_GENERIC + +ECP write binary #7 (odd, compressed, buffer just fits) +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":COMPRESSED:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0 ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 1e50499b8..b273a70a1 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -225,7 +225,7 @@ ecp_fast_mod:id:N END_CASE BEGIN_CASE -ecp_write_binary:id:x:y:z:out:blen:ret +ecp_write_binary:id:x:y:z:format:out:blen:ret { ecp_group grp; ecp_point P; @@ -243,13 +243,13 @@ ecp_write_binary:id:x:y:z:out:blen:ret TEST_ASSERT( mpi_read_string( &P.Y, 16, {y} ) == 0 ); TEST_ASSERT( mpi_read_string( &P.Z, 16, {z} ) == 0 ); - TEST_ASSERT( ecp_write_binary( &grp, &P, &olen, buf, {blen} ) == {ret} ); +#define POLARSSL_ECP_PF_UNKNOWN -1 + TEST_ASSERT( ecp_write_binary( &grp, &P, POLARSSL_ECP_PF_{format}, + &olen, buf, {blen} ) == {ret} ); if( {ret} == 0 ) { - TEST_ASSERT( olen == strlen({out}) / 2 ); - - hexify( str, buf, {blen} ); + hexify( str, buf, olen ); TEST_ASSERT( strcasecmp( (char *) str, {out} ) == 0 ); } From 5e402d88ea0b2d8d2878d40aaa6c10c8cf95bb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 24 Nov 2012 16:19:42 +0100 Subject: [PATCH 44/76] Added ecp_read_binary(). --- include/polarssl/ecp.h | 21 ++++++++++++++- library/ecp.c | 27 ++++++++++++++++++++ tests/suites/test_suite_ecp.data | 21 +++++++++++++++ tests/suites/test_suite_ecp.function | 38 ++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index cd4dd9b27..189e3f253 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -218,7 +218,7 @@ int ecp_group_read_string( ecp_group *grp, int radix, /** * \brief Export a point into unsigned binary data * - * \param grp Group the point belongs to + * \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 ouput @@ -230,6 +230,25 @@ int ecp_group_read_string( ecp_group *grp, int radix, int ecp_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 format Point format, must be POLARSSL_ECP_PF_UNCOMPRESSED for now + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_GENERIC if input is invalid + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note This function does NOT check that the point actually + * belongs to the given group, see ecp_check_pubkey() for + * that. + */ +int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, + const unsigned char *buf, size_t ilen ); /** * \brief Set a group using well-known domain parameters * diff --git a/library/ecp.c b/library/ecp.c index 6501fbe9f..dd913bead 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -228,6 +228,33 @@ cleanup: return( ret ); } +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, + const unsigned char *buf, size_t ilen ) { + int ret; + size_t plen; + + if( format != POLARSSL_ECP_PF_UNCOMPRESSED ) + return( POLARSSL_ERR_ECP_GENERIC ); + + if( ilen == 1 && buf[0] == 0x00 ) + return( ecp_set_zero( P ) ); + + plen = mpi_size( &grp-> P ); + + if( ilen != 2 * plen + 1 || buf[0] != 0x04 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + MPI_CHK( mpi_read_binary( &P->X, buf + 1, plen ) ); + MPI_CHK( mpi_read_binary( &P->Y, buf + 1 + plen, plen ) ); + MPI_CHK( mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + /* * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi. * See the documentation of struct ecp_group. diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index e84ac045e..605af820e 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -163,6 +163,27 @@ ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6 ECP write binary #7 (odd, compressed, buffer just fits) ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":COMPRESSED:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0 +ECP read binary #0 (invalid format) +ecp_read_binary:SECP192R1:"00":UNKNOWN:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #1 (zero, invalid ilen) +ecp_read_binary:SECP192R1:"0000":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #2 (zero, invalid first byte) +ecp_read_binary:SECP192R1:"01":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #3 (zero, OK) +ecp_read_binary:SECP192R1:"00":UNCOMPRESSED:"01":"01":"00":0 + +ECP read binary #4 (non-zero, invalid ilen) +ecp_read_binary:SECP192R1:"04001122":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #5 (non-zero, invalid first byte) +ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":POLARSSL_ERR_ECP_GENERIC + +ECP read binary #6 (non-zero, OK) +ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index b273a70a1..fdd3da2a9 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -257,6 +257,44 @@ ecp_write_binary:id:x:y:z:format:out:blen:ret } END_CASE +BEGIN_CASE +ecp_read_binary:id:input:format:x:y:z:ret +{ + ecp_group grp; + ecp_point P; + mpi X, Y, Z; + int ilen; + unsigned char buf[256]; + + memset( buf, 0, sizeof( buf ) ); + + ecp_group_init( &grp ); ecp_point_init( &P ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( mpi_read_string( &X, 16, {x} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Y, 16, {y} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Z, 16, {z} ) == 0 ); + + ilen = unhexify( buf, {input} ); + +#define POLARSSL_ECP_PF_UNKNOWN -1 + TEST_ASSERT( ecp_read_binary( &grp, &P, POLARSSL_ECP_PF_{format}, + buf, ilen ) == {ret} ); + + if( {ret} == 0 ) + { + TEST_ASSERT( mpi_cmp_mpi( &P.X, &X ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &P.Y, &Y ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &P.Z, &Z ) == 0 ); + } + + ecp_group_free( &grp ); ecp_point_free( &P ); + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); +} +END_CASE + BEGIN_CASE ecp_selftest: { From a95919b4c78ced3b494d6028cfed6799b034d743 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 16 Jan 2013 17:00:05 +0100 Subject: [PATCH 45/76] Added ECP files to Makefiles as well --- library/Makefile | 3 ++- programs/Makefile | 5 +++++ tests/Makefile | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/library/Makefile b/library/Makefile index 603f5d16e..6852e95df 100644 --- a/library/Makefile +++ b/library/Makefile @@ -39,7 +39,8 @@ OBJS= aes.o arc4.o asn1parse.o \ blowfish.o camellia.o \ certs.o cipher.o cipher_wrap.o \ ctr_drbg.o debug.o des.o \ - dhm.o entropy.o entropy_poll.o \ + dhm.o ecp.o \ + entropy.o entropy_poll.o \ error.o gcm.o havege.o \ md.o md_wrap.o md2.o \ md4.o md5.o net.o \ diff --git a/programs/Makefile b/programs/Makefile index 9b0d1f531..388b029e2 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -38,6 +38,7 @@ APPS = aes/aescrypt2 aes/crypt_and_hash \ random/gen_random_ctr_drbg \ test/ssl_cert_test test/benchmark \ test/selftest test/ssl_test \ + test/ecp-bench \ util/strerror \ x509/cert_app x509/crl_app \ x509/cert_req @@ -174,6 +175,10 @@ test/benchmark: test/benchmark.c ../library/libpolarssl.a echo " CC test/benchmark.c" $(CC) $(CFLAGS) $(OFLAGS) test/benchmark.c $(LDFLAGS) -o $@ +test/ecp-bench: test/ecp-bench.c ../library/libpolarssl.a + echo " CC test/ecp-bench.c" + $(CC) $(CFLAGS) $(OFLAGS) test/ecp-bench.c $(LDFLAGS) -o $@ + test/selftest: test/selftest.c ../library/libpolarssl.a echo " CC test/selftest.c" $(CC) $(CFLAGS) $(OFLAGS) test/selftest.c $(LDFLAGS) -o $@ diff --git a/tests/Makefile b/tests/Makefile index 4c97aa5d3..be5e09831 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -30,6 +30,7 @@ APPS = test_suite_aes test_suite_arc4 \ test_suite_cipher.des test_suite_cipher.null \ test_suite_ctr_drbg test_suite_debug \ test_suite_des test_suite_dhm \ + test_suite_ecp \ test_suite_error test_suite_gcm.decrypt \ test_suite_gcm.decrypt test_suite_hmac_shax \ test_suite_md test_suite_mdx \ @@ -127,6 +128,10 @@ test_suite_dhm: test_suite_dhm.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ +test_suite_ecp: test_suite_ecp.c ../library/libpolarssl.a + echo " CC $@.c" + $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ + test_suite_error: test_suite_error.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ From cf4365f560c0bc8f3c064d34f92c959f8d7bd956 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 16 Jan 2013 17:00:43 +0100 Subject: [PATCH 46/76] Updated error codes for ECP --- include/polarssl/ecp.h | 7 +++---- include/polarssl/error.h | 3 ++- library/ecp.c | 2 +- library/error.c | 11 +++++++++++ scripts/generate_errors.pl | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 189e3f253..2d20693b6 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -3,7 +3,7 @@ * * \brief Elliptic curves over GF(p) * - * Copyright (C) 2012, Brainspark B.V. + * Copyright (C) 2006-2013, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker @@ -31,10 +31,9 @@ /* * ECP error codes - * - * (Only one error code available...) */ -#define POLARSSL_ERR_ECP_GENERIC -0x007E /**< Generic ECP error */ +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_ECP_GENERIC -0x4F00 /**< Generic ECP error */ /** * \brief ECP point structure (jacobian coordinates) diff --git a/include/polarssl/error.h b/include/polarssl/error.h index 736e8a795..32dc0a7fd 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -3,7 +3,7 @@ * * \brief Error to string translation * - * Copyright (C) 2006-2010, Brainspark B.V. + * Copyright (C) 2006-2013, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker @@ -76,6 +76,7 @@ * X509 2 21 * DHM 3 6 * RSA 4 9 + * ECP 4 1 (Started from top) * MD 5 4 * CIPHER 6 5 * SSL 6 2 (Started from top) diff --git a/library/ecp.c b/library/ecp.c index dd913bead..119c75470 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1,7 +1,7 @@ /* * Elliptic curves over GF(p) * - * Copyright (C) 2012, Brainspark B.V. + * Copyright (C) 2006-2013, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker diff --git a/library/error.c b/library/error.c index 03abc3265..1e96ebba3 100644 --- a/library/error.c +++ b/library/error.c @@ -63,6 +63,10 @@ #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 @@ -182,6 +186,13 @@ void error_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); #endif /* POLARSSL_DHM_C */ +#if defined(POLARSSL_ECP_C) + if( use_ret == -(POLARSSL_ERR_ECP_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_ECP_GENERIC) ) + snprintf( buf, buflen, "ECP - Generic ECP error" ); +#endif /* POLARSSL_ECP_C */ + #if defined(POLARSSL_MD_C) if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) ) snprintf( buf, buflen, "MD - The selected feature is not available" ); diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index e89496490..8184d78c2 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -12,7 +12,7 @@ my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", "BASE64", "XTEA", "PBKDF2", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "MD2", "MD4", "MD5", "SHA1", "SHA2", "SHA4", "GCM" ); -my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "MD", "CIPHER", "SSL" ); +my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL" ); my $line_separator = $/; undef $/; From 45a035a9acceb935132fa6d45657f252e3f32b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 14:42:45 +0100 Subject: [PATCH 47/76] Add ecp_gen_keypair() --- include/polarssl/ecp.h | 16 ++++++++++++++++ library/ecp.c | 27 +++++++++++++++++++++++++++ tests/suites/test_suite_ecp.data | 3 +++ tests/suites/test_suite_ecp.function | 27 +++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 2d20693b6..6c52f9622 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -309,6 +309,22 @@ int ecp_sub( const ecp_group *grp, ecp_point *R, int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); +/** + * \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 + */ +int ecp_gen_keypair( const ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + /** * \brief Checkup routine * diff --git a/library/ecp.c b/library/ecp.c index 119c75470..9153f11ad 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1127,6 +1127,33 @@ cleanup: return( ret ); } +/* + * Generate a keypair (SEC1 3.2.1) + */ +int ecp_gen_keypair( const ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int count = 0; + size_t n_size = (grp->nbits + 7) / 8; + + /* + * Generate d such that 1 <= n < N + */ + do + { + mpi_fill_random( d, n_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( d, &grp->N ) >= 0 ) + mpi_shift_r( d, 1 ); + + if( count++ > 10 ) + return( POLARSSL_ERR_ECP_GENERIC ); + } + while( mpi_cmp_int( d, 1 ) < 0 ); + + return( ecp_mul( grp, Q, d, &grp->G ) ); +} #if defined(POLARSSL_SELF_TEST) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 605af820e..08a5e2bc7 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -184,6 +184,9 @@ ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ce ECP read binary #6 (non-zero, OK) ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 +ECP gen keypair +ecp_gen_keypair:SECP192R1 + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index fdd3da2a9..290b786de 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -295,6 +295,33 @@ ecp_read_binary:id:input:format:x:y:z:ret } END_CASE +BEGIN_CASE +ecp_gen_keypair:id +{ + ecp_group grp; + ecp_point Q; + mpi d; + rnd_pseudo_info rnd_info; + + ecp_group_init( &grp ); + ecp_point_init( &Q ); + mpi_init( &d ); + memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( ecp_gen_keypair( &grp, &d, &Q, &rnd_pseudo_rand, &rnd_info ) + == 0 ); + + TEST_ASSERT( mpi_cmp_mpi( &d, &grp.N ) < 0 ); + TEST_ASSERT( mpi_cmp_int( &d, 1 ) >= 0 ); + + ecp_group_free( &grp ); + ecp_point_free( &Q ); + mpi_free( &d ); +} +END_CASE + BEGIN_CASE ecp_selftest: { From 0bad5c238135e5124881927093e8ee04ceb167f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 15:30:46 +0100 Subject: [PATCH 48/76] Add skeleton ecdh.[ch] --- include/polarssl/config.h | 15 +++++++++++- include/polarssl/ecdh.h | 47 ++++++++++++++++++++++++++++++++++++ include/polarssl/ecp.h | 2 +- library/CMakeLists.txt | 1 + library/ecdh.c | 51 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 include/polarssl/ecdh.h create mode 100644 library/ecdh.c diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 2493233b9..3b682d362 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -836,11 +836,24 @@ * Enable the elliptic curve over GF(p) library. * * Module: library/ecp.c - * Caller: + * Caller: library/ecdh.c * * Requires: POLARSSL_BIGNUM_C */ #define POLARSSL_ECP_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library + * + * Module: library/ecdh.c + * Caller: + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDH_C + /* \} name */ #endif /* config.h */ diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h new file mode 100644 index 000000000..5c9be4595 --- /dev/null +++ b/include/polarssl/ecdh.h @@ -0,0 +1,47 @@ +/** + * \file ecdh.h + * + * \brief Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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 "polarssl/ecp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecdh_self_test( int verbose ); + +#endif diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 6c52f9622..e1b099540 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -27,7 +27,7 @@ #ifndef POLARSSL_ECP_H #define POLARSSL_ECP_H -#include "bignum.h" +#include "polarssl/bignum.h" /* * ECP error codes diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 704a4b08f..28bbedc72 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -17,6 +17,7 @@ set(src des.c dhm.c ecp.c + ecdh.c entropy.c entropy_poll.c error.c diff --git a/library/ecdh.c b/library/ecdh.c new file mode 100644 index 000000000..a706b2e29 --- /dev/null +++ b/library/ecdh.c @@ -0,0 +1,51 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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 + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_ECP_C) + +#include "polarssl/ecdh.h" + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecdh_self_test( int verbose ) +{ + return( verbose++ ); +} + +#endif + +#endif /* defined(POLARSSL_ECP_C) */ From 6545ca7bed5ae6684ec5f4913a7f332b500fd2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 16:05:22 +0100 Subject: [PATCH 49/76] Add ECDH primitives --- include/polarssl/ecdh.h | 36 +++++++++++++++++++++++++++++++++--- include/polarssl/ecp.h | 11 +++++++++++ library/ecdh.c | 39 +++++++++++++++++++++++++++++++++++++++ library/ecp.c | 8 ++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h index 5c9be4595..ad131061c 100644 --- a/include/polarssl/ecdh.h +++ b/include/polarssl/ecdh.h @@ -33,9 +33,35 @@ extern "C" { #endif -#ifdef __cplusplus -} -#endif +/** + * \brief Generate a public key + * + * \param grp ECP group + * \param d Destination MPI (secret exponent) + * \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( const ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute shared secret + * + * \param grp ECP group + * \param z Destination MPI (shared secret) + * \param Q Public key from other party + * \param d Our secret exponent + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdh_compute_shared( const ecp_group *grp, mpi *z, + const ecp_point *Q, const mpi *d ); /** * \brief Checkup routine @@ -44,4 +70,8 @@ extern "C" { */ int ecdh_self_test( int verbose ); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index e1b099540..b8b19978b 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -147,11 +147,22 @@ void ecp_group_free( ecp_group *grp ); /** * \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 Copy the contents of point Q into P * diff --git a/library/ecdh.c b/library/ecdh.c index a706b2e29..15158990a 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -35,6 +35,45 @@ #include "polarssl/ecdh.h" +/* + * Generate public key: simple wrapper around ecp_gen_keypair + */ +int ecdh_gen_public( const 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( const ecp_group *grp, mpi *z, + const ecp_point *Q, const mpi *d ) +{ + 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 ) ); + + if( ecp_is_zero( &P ) ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + MPI_CHK( mpi_copy( z, &P.X ) ); + +cleanup: + ecp_point_free( &P ); + + return( ret ); +} + #if defined(POLARSSL_SELF_TEST) diff --git a/library/ecp.c b/library/ecp.c index 9153f11ad..b8b0dfc74 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -121,6 +121,14 @@ cleanup: return( ret ); } +/* + * Tell if a point is zero + */ +int ecp_is_zero( ecp_point *pt ) +{ + return( mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + /* * Copy the contents of Q into P */ From 61ce13b72888e480ba9b108ecec49ec2ae7fa4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 16:20:32 +0100 Subject: [PATCH 50/76] Basic tests for ECDH primitive --- tests/CMakeLists.txt | 1 + tests/suites/test_suite_ecdh.data | 15 +++++++++++ tests/suites/test_suite_ecdh.function | 39 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 tests/suites/test_suite_ecdh.data create mode 100644 tests/suites/test_suite_ecdh.function diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fda5bd36b..863d7a5a9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -46,6 +46,7 @@ add_test_suite(debug) add_test_suite(des) add_test_suite(dhm) add_test_suite(ecp) +add_test_suite(ecdh) add_test_suite(error) add_test_suite(gcm gcm.encrypt) add_test_suite(gcm gcm.decrypt) diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data new file mode 100644 index 000000000..5b98b6285 --- /dev/null +++ b/tests/suites/test_suite_ecdh.data @@ -0,0 +1,15 @@ +ECDH primitive agreement #1 +ecdh_primitive_agreement:SECP192R1 + +ECDH primitive agreement #2 +ecdh_primitive_agreement:SECP224R1 + +ECDH primitive agreement #3 +ecdh_primitive_agreement:SECP256R1 + +ECDH primitive agreement #4 +ecdh_primitive_agreement:SECP384R1 + +ECDH primitive agreement #5 +ecdh_primitive_agreement:SECP521R1 + diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function new file mode 100644 index 000000000..76e6977a9 --- /dev/null +++ b/tests/suites/test_suite_ecdh.function @@ -0,0 +1,39 @@ +BEGIN_HEADER +#include +END_HEADER + +BEGIN_DEPENDENCIES +depends_on:POLARSSL_ECDH_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C +END_DEPENDENCIES + +BEGIN_CASE +ecdh_primitive_agreement:id +{ + ecp_group grp; + ecp_point qA, qB; + mpi dA, dB, zA, zB; + rnd_pseudo_info rnd_info; + + ecp_group_init( &grp ); + ecp_point_init( &qA ); ecp_point_init( &qB ); + mpi_init( &dA ); mpi_init( &dB ); + mpi_init( &zA ); mpi_init( &zB ); + memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( ecdh_gen_public( &grp, &dA, &qA, &rnd_pseudo_rand, &rnd_info ) + == 0 ); + TEST_ASSERT( ecdh_gen_public( &grp, &dB, &qB, &rnd_pseudo_rand, &rnd_info ) + == 0 ); + TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA ) == 0 ); + TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB ) == 0 ); + + TEST_ASSERT( mpi_cmp_mpi( &zA, &zB ) == 0 ); + + ecp_group_free( &grp ); + ecp_point_free( &qA ); ecp_point_free( &qB ); + mpi_free( &dA ); mpi_free( &dB ); + mpi_free( &zA ); mpi_free( &zB ); +} +END_CASE From 2aea1416f93e6822ce8072e9395b7fed1d1c8eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 16:33:44 +0100 Subject: [PATCH 51/76] Add skeleton ecdsa.[ch] --- include/polarssl/config.h | 15 +++++++++++- include/polarssl/ecdsa.h | 47 ++++++++++++++++++++++++++++++++++++ library/CMakeLists.txt | 1 + library/ecdh.c | 4 +-- library/ecdsa.c | 51 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 include/polarssl/ecdsa.h create mode 100644 library/ecdsa.c diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 3b682d362..362c237d2 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -837,6 +837,7 @@ * * Module: library/ecp.c * Caller: library/ecdh.c + * library/ecdsa.c * * Requires: POLARSSL_BIGNUM_C */ @@ -845,7 +846,7 @@ /** * \def POLARSSL_ECDH_C * - * Enable the elliptic curve Diffie-Hellman library + * Enable the elliptic curve Diffie-Hellman library. * * Module: library/ecdh.c * Caller: @@ -854,6 +855,18 @@ */ #define POLARSSL_ECDH_C +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDSA_C + /* \} name */ #endif /* config.h */ diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h new file mode 100644 index 000000000..cf7a78843 --- /dev/null +++ b/include/polarssl/ecdsa.h @@ -0,0 +1,47 @@ +/** + * \file ecdsa.h + * + * \brief Elliptic curve DSA + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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 "polarssl/ecp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecdsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 28bbedc72..6bc46e047 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -18,6 +18,7 @@ set(src dhm.c ecp.c ecdh.c + ecdsa.c entropy.c entropy_poll.c error.c diff --git a/library/ecdh.c b/library/ecdh.c index 15158990a..1b4fcd3b2 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -31,7 +31,7 @@ #include "polarssl/config.h" -#if defined(POLARSSL_ECP_C) +#if defined(POLARSSL_ECDH_C) #include "polarssl/ecdh.h" @@ -87,4 +87,4 @@ int ecdh_self_test( int verbose ) #endif -#endif /* defined(POLARSSL_ECP_C) */ +#endif /* defined(POLARSSL_ECDH_C) */ diff --git a/library/ecdsa.c b/library/ecdsa.c new file mode 100644 index 000000000..09d14f933 --- /dev/null +++ b/library/ecdsa.c @@ -0,0 +1,51 @@ +/* + * Elliptic curve DSA + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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 + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_ECDSA_C) + +#include "polarssl/ecdsa.h" + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecdsa_self_test( int verbose ) +{ + return( verbose++ ); +} + +#endif + +#endif /* defined(POLARSSL_ECDSA_C) */ From b309ab293625819da31a894e345188708c847ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 17:24:59 +0100 Subject: [PATCH 52/76] Add ECDSA sign primitive --- include/polarssl/ecdsa.h | 19 +++++++++++++ library/ecdsa.c | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h index cf7a78843..39a062666 100644 --- a/include/polarssl/ecdsa.h +++ b/include/polarssl/ecdsa.h @@ -33,6 +33,25 @@ 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( const 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 ); + /** * \brief Checkup routine * diff --git a/library/ecdsa.c b/library/ecdsa.c index 09d14f933..a8f29c134 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -35,6 +35,67 @@ #include "polarssl/ecdsa.h" +/* + * 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( const 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; + size_t n_size; + ecp_point R; + mpi k, e; + + ecp_point_init( &R ); + mpi_init( &k ); + mpi_init( &e ); + + sign_tries = 0; + do + { + /* + * Steps 1-3: generate a suitable ephemeral keypair + */ + key_tries = 0; + do + { + MPI_CHK( ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MPI_CHK( mpi_copy( r, &R.X ) ); + + if( key_tries++ > 10 ) + return( POLARSSL_ERR_ECP_GENERIC ); + } + while( mpi_cmp_int( r, 0 ) == 0 ); + + /* + * Step 5: derive MPI from hashed message + */ + n_size = (grp->nbits + 7) / 8; + MPI_CHK( mpi_read_binary( &e, buf, blen > n_size ? n_size : blen ) ); + + /* + * Step 6: compute s = (e + r * d) / k mod n + */ + MPI_CHK( mpi_mul_mpi( s, r, d ) ); + MPI_CHK( mpi_add_mpi( &e, &e, s ) ); + 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 ) + return( POLARSSL_ERR_ECP_GENERIC ); + } + while( mpi_cmp_int( s, 0 ) == 0 ); + +cleanup: + ecp_point_free( &R ); + mpi_free( &k ); + mpi_free( &e ); + + return( ret ); +} #if defined(POLARSSL_SELF_TEST) From 3aeb5a7192b8e5259b517ae0a7f6272abfe83fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 18:05:50 +0100 Subject: [PATCH 53/76] Add ECDSA signature primitive. --- include/polarssl/ecdsa.h | 18 +++++++++ library/ecdsa.c | 84 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h index 39a062666..2ad986d64 100644 --- a/include/polarssl/ecdsa.h +++ b/include/polarssl/ecdsa.h @@ -52,6 +52,24 @@ int ecdsa_sign( const 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 ); +/** + * \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( const ecp_group *grp, + const unsigned char *buf, size_t blen, + const ecp_point *Q, const mpi *r, const mpi *s); + /** * \brief Checkup routine * diff --git a/library/ecdsa.c b/library/ecdsa.c index a8f29c134..d6834574d 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -35,6 +35,17 @@ #include "polarssl/ecdsa.h" +/* + * 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 ) +{ + size_t n_size = (grp->nbits + 7) / 8; + return( mpi_read_binary( x, buf, blen > n_size ? n_size : blen ) ); +} + /* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) @@ -44,7 +55,6 @@ int ecdsa_sign( const ecp_group *grp, mpi *r, mpi *s, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, key_tries, sign_tries; - size_t n_size; ecp_point R; mpi k, e; @@ -72,8 +82,7 @@ int ecdsa_sign( const ecp_group *grp, mpi *r, mpi *s, /* * Step 5: derive MPI from hashed message */ - n_size = (grp->nbits + 7) / 8; - MPI_CHK( mpi_read_binary( &e, buf, blen > n_size ? n_size : blen ) ); + MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); /* * Step 6: compute s = (e + r * d) / k mod n @@ -97,6 +106,75 @@ cleanup: return( ret ); } +/* + * 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( const 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 ); + + /* + * 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 ) + { + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + } + + /* + * 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 + */ + MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G ) ); + MPI_CHK( ecp_mul( grp, &P, &u2, Q ) ); + MPI_CHK( ecp_add( grp, &R, &R, &P ) ); + + if( ecp_is_zero( &R ) ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Step 6: check that xR == r + */ + if( mpi_cmp_mpi( &R.X, r ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + ecp_point_free( &R ); ecp_point_free( &P ); + mpi_free( &e ); mpi_free( &s_inv ); mpi_free( &u1 ); mpi_free( &u2 ); + + return( ret ); +} + + #if defined(POLARSSL_SELF_TEST) /* From d1c7150bf51c8450381fd1b53d0a41191cf6c700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 26 Jan 2013 19:09:07 +0100 Subject: [PATCH 54/76] Basic tests for ECDSA. --- tests/CMakeLists.txt | 1 + tests/suites/test_suite_ecdsa.data | 15 +++++++++++ tests/suites/test_suite_ecdsa.function | 37 ++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/suites/test_suite_ecdsa.data create mode 100644 tests/suites/test_suite_ecdsa.function diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 863d7a5a9..63224b261 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -47,6 +47,7 @@ add_test_suite(des) add_test_suite(dhm) add_test_suite(ecp) add_test_suite(ecdh) +add_test_suite(ecdsa) add_test_suite(error) add_test_suite(gcm gcm.encrypt) add_test_suite(gcm gcm.decrypt) diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data new file mode 100644 index 000000000..b13d8889b --- /dev/null +++ b/tests/suites/test_suite_ecdsa.data @@ -0,0 +1,15 @@ +ECDSA sign-verify #1 +ecdsa_sign_verify:SECP192R1 + +ECDSA sign-verify #2 +ecdsa_sign_verify:SECP224R1 + +ECDSA sign-verify #3 +ecdsa_sign_verify:SECP256R1 + +ECDSA sign-verify #4 +ecdsa_sign_verify:SECP384R1 + +ECDSA sign-verify #5 +ecdsa_sign_verify:SECP521R1 + diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function new file mode 100644 index 000000000..e90938c63 --- /dev/null +++ b/tests/suites/test_suite_ecdsa.function @@ -0,0 +1,37 @@ +BEGIN_HEADER +#include +END_HEADER + +BEGIN_DEPENDENCIES +depends_on:POLARSSL_ECDSA_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C +END_DEPENDENCIES + +BEGIN_CASE +ecdsa_sign_verify:id +{ + ecp_group grp; + ecp_point Q; + mpi d, r, s; + rnd_pseudo_info rnd_info; + unsigned char buf[66]; + + ecp_group_init( &grp ); + ecp_point_init( &Q ); + mpi_init( &d ); mpi_init( &r ); mpi_init( &s ); + memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + + /* prepare material for signature */ + TEST_ASSERT( rnd_pseudo_rand( &rnd_info, buf, sizeof( buf ) ) == 0 ); + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + TEST_ASSERT( ecp_gen_keypair( &grp, &d, &Q, &rnd_pseudo_rand, &rnd_info ) + == 0 ); + + TEST_ASSERT( ecdsa_sign( &grp, &r, &s, &d, buf, sizeof( buf ), + &rnd_pseudo_rand, &rnd_info ) == 0 ); + TEST_ASSERT( ecdsa_verify( &grp, buf, sizeof( buf ), &Q, &r, &s ) == 0 ); + + ecp_group_free( &grp ); + ecp_point_free( &Q ); + mpi_free( &d ); mpi_free( &r ); mpi_free( &s ); +} +END_CASE From 602a8973d748d5ebbfc40e9d2224ae08cbecff7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 27 Jan 2013 08:10:28 +0100 Subject: [PATCH 55/76] ECDSA : test vectors from RFC 4754 --- tests/suites/helpers.function | 46 ++++++++++++++++++++++++++ tests/suites/test_suite_ecdsa.data | 29 ++++++++++------ tests/suites/test_suite_ecdsa.function | 38 ++++++++++++++++++++- 3 files changed, 102 insertions(+), 11 deletions(-) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index 2f1b26cf8..208e7e675 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -218,3 +218,49 @@ static int rnd_pseudo_rand( void *rng_state, unsigned char *output, size_t len ) return( 0 ); } + +/** + * This function returns a buffer given as a hex string. + * + * The buffer is reversed so that the following are equivalent: + * mpi_fill_random( x, len, not_rnd, str ); + * mpi_read_string( x, 16, str ); + * (So, not random at all. Usefull to match test vectors.) + * Based on unhexify(), just reversed (changes marked by "sic") + */ +static int not_rnd( void *in, unsigned char *out, size_t len ) +{ + unsigned char *obuf; + const char *ibuf = in; + unsigned char c, c2; + assert( len == strlen(ibuf) / 2 ); + assert(!(strlen(ibuf) %1)); // must be even number of bytes + + obuf = out + (len - 1); // sic + while (*ibuf != 0) + { + c = *ibuf++; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + assert( 0 ); + + c2 = *ibuf++; + if( c2 >= '0' && c2 <= '9' ) + c2 -= '0'; + else if( c2 >= 'a' && c2 <= 'f' ) + c2 -= 'a' - 10; + else if( c2 >= 'A' && c2 <= 'F' ) + c2 -= 'A' - 10; + else + assert( 0 ); + + *obuf-- = ( c << 4 ) | c2; // sic + } + + return( 0 ); +} diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index b13d8889b..15848bc2e 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -1,15 +1,24 @@ -ECDSA sign-verify #1 -ecdsa_sign_verify:SECP192R1 +ECDSA random sign-verify #1 +ecdsa_random:SECP192R1 -ECDSA sign-verify #2 -ecdsa_sign_verify:SECP224R1 +ECDSA random sign-verify #2 +ecdsa_random:SECP224R1 -ECDSA sign-verify #3 -ecdsa_sign_verify:SECP256R1 +ECDSA random sign-verify #3 +ecdsa_random:SECP256R1 -ECDSA sign-verify #4 -ecdsa_sign_verify:SECP384R1 +ECDSA random sign-verify #4 +ecdsa_random:SECP384R1 -ECDSA sign-verify #5 -ecdsa_sign_verify:SECP521R1 +ECDSA random sign-verify #5 +ecdsa_random:SECP521R1 + +ECDSA rfc 4754 p256 +ecdsa_test_vectors:SECP256R1:DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F:2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970:6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D:9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B154BF61AF1D5A6DECE:BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD:CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C:86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315 + +ECDSA rfc 4754 p384 +ecdsa_test_vectors:SECP384R1:0BEB646634BA87735D77AE4809A0EBEA865535DE4C1E1DCB692E84708E81A5AF62E528C38B2A81B35309668D73524D9F:96281BF8DD5E0525CA049C048D345D3082968D10FEDF5C5ACA0C64E6465A97EA5CE10C9DFEC21797415710721F437922:447688BA94708EB6E2E4D59F6AB6D7EDFF9301D249FE49C33096655F5D502FAD3D383B91C5E7EDAA2B714CC99D5743CA:B4B74E44D71A13D568003D7489908D564C7761E229C58CBFA18950096EB7463B854D7FA992F934D927376285E63414FA:CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7:FB017B914E29149432D8BAC29A514640B46F53DDAB2C69948084E2930F1C8F7E08E07C9C63F2D21A07DCB56A6AF56EB3:B263A1305E057F984D38726A1B46874109F417BCA112674C528262A40A629AF1CBB9F516CE0FA7D2FF630863A00E8B9F + +ECDSA sign rfc 4754 p521 +ecdsa_test_vectors:SECP521R1:0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF5849120597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B375FA1:0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD19052A8:006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEAE643:00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B956C2F:DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F:0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE544320552251:017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F866472660 diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index e90938c63..89f9979a6 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -7,7 +7,7 @@ depends_on:POLARSSL_ECDSA_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C END_DEPENDENCIES BEGIN_CASE -ecdsa_sign_verify:id +ecdsa_random:id { ecp_group grp; ecp_point Q; @@ -35,3 +35,39 @@ ecdsa_sign_verify:id mpi_free( &d ); mpi_free( &r ); mpi_free( &s ); } END_CASE + +BEGIN_CASE +ecdsa_test_vectors:id:d:xQ:yQ:k:hash:r:s +{ + ecp_group grp; + ecp_point Q; + mpi d, r, s, r_check, s_check; + unsigned char buf[66]; + size_t len; + + ecp_group_init( &grp ); + ecp_point_init( &Q ); + mpi_init( &d ); mpi_init( &r ); mpi_init( &s ); + mpi_init( &r_check ); mpi_init( &s_check ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + TEST_ASSERT( ecp_point_read_string( &Q, 16, "{xQ}", "{yQ}" ) == 0 ); + TEST_ASSERT( mpi_read_string( &d, 16, "{d}" ) == 0 ); + TEST_ASSERT( mpi_read_string( &r_check, 16, "{r}" ) == 0 ); + TEST_ASSERT( mpi_read_string( &s_check, 16, "{s}" ) == 0 ); + len = unhexify(buf, "{hash}"); + + TEST_ASSERT( ecdsa_sign( &grp, &r, &s, &d, buf, len, + ¬_rnd, "{k}" ) == 0 ); + + TEST_ASSERT( mpi_cmp_mpi( &r, &r_check ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &s, &s_check ) == 0 ); + + TEST_ASSERT( ecdsa_verify( &grp, buf, len, &Q, &r_check, &s_check ) == 0 ); + + ecp_group_free( &grp ); + ecp_point_free( &Q ); + mpi_free( &d ); mpi_free( &r ); mpi_free( &s ); + mpi_free( &r_check ); mpi_free( &s_check ); +} +END_CASE From 007b7177ef8f7912ad6f612d84d2c3533fd4e447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 27 Jan 2013 08:56:21 +0100 Subject: [PATCH 56/76] ECDH : add test vectors from RFC 5903. --- tests/suites/test_suite_ecdh.data | 28 ++++++++++------- tests/suites/test_suite_ecdh.function | 43 ++++++++++++++++++++++++++- tests/suites/test_suite_ecp.data | 9 ------ 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data index 5b98b6285..0926ed55e 100644 --- a/tests/suites/test_suite_ecdh.data +++ b/tests/suites/test_suite_ecdh.data @@ -1,15 +1,23 @@ -ECDH primitive agreement #1 -ecdh_primitive_agreement:SECP192R1 +ECDH primitive random #1 +ecdh_primitive_random:SECP192R1 -ECDH primitive agreement #2 -ecdh_primitive_agreement:SECP224R1 +ECDH primitive random #2 +ecdh_primitive_random:SECP224R1 -ECDH primitive agreement #3 -ecdh_primitive_agreement:SECP256R1 +ECDH primitive random #3 +ecdh_primitive_random:SECP256R1 -ECDH primitive agreement #4 -ecdh_primitive_agreement:SECP384R1 +ECDH primitive random #4 +ecdh_primitive_random:SECP384R1 -ECDH primitive agreement #5 -ecdh_primitive_agreement:SECP521R1 +ECDH primitive random #5 +ecdh_primitive_random:SECP521R1 +ECDH primitive rfc 5903 p256 +ecdh_primitive_testvec:SECP256R1:C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433:DAD0B65394221CF9B051E1FECA5787D098DFE637FC90B9EF945D0C3772581180:5271A0461CDB8252D61F1C456FA3E59AB1F45B33ACCF5F58389E0577B8990BB3:C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53:D12DFB5289C8D4F81208B70270398C342296970A0BCCB74C736FC7554494BF63:56FBF3CA366CC23E8157854C13C58D6AAC23F046ADA30F8353E74F33039872AB:D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE + +ECDH primitive rfc 5903 p384 +ecdh_primitive_testvec:SECP384R1:099F3C7034D4A2C699884D73A375A67F7624EF7C6B3C0F160647B67414DCE655E35B538041E649EE3FAEF896783AB194:667842D7D180AC2CDE6F74F37551F55755C7645C20EF73E31634FE72B4C55EE6DE3AC808ACB4BDB4C88732AEE95F41AA:9482ED1FC0EEB9CAFC4984625CCFC23F65032149E0E144ADA024181535A0F38EEB9FCFF3C2C947DAE69B4C634573A81C:41CB0779B4BDB85D47846725FBEC3C9430FAB46CC8DC5060855CC9BDA0AA2942E0308312916B8ED2960E4BD55A7448FC:E558DBEF53EECDE3D3FCCFC1AEA08A89A987475D12FD950D83CFA41732BC509D0D1AC43A0336DEF96FDA41D0774A3571:DCFBEC7AACF3196472169E838430367F66EEBE3C6E70C416DD5F0C68759DD1FFF83FA40142209DFF5EAAD96DB9E6386C:11187331C279962D93D604243FD592CB9D0A926F422E47187521287E7156C5C4D603135569B9E9D09CF5D4A270F59746 + +ECDH primitive rfc 5903 p521 +ecdh_primitive_testvec:SECP521R1:0037ADE9319A89F4DABDB3EF411AACCCA5123C61ACAB57B5393DCE47608172A095AA85A30FE1C2952C6771D937BA9777F5957B2639BAB072462F68C27A57382D4A52:0015417E84DBF28C0AD3C278713349DC7DF153C897A1891BD98BAB4357C9ECBEE1E3BF42E00B8E380AEAE57C2D107564941885942AF5A7F4601723C4195D176CED3E:017CAE20B6641D2EEB695786D8C946146239D099E18E1D5A514C739D7CB4A10AD8A788015AC405D7799DC75E7B7D5B6CF2261A6A7F1507438BF01BEB6CA3926F9582:0145BA99A847AF43793FDD0E872E7CDFA16BE30FDC780F97BCCC3F078380201E9C677D600B343757A3BDBF2A3163E4C2F869CCA7458AA4A4EFFC311F5CB151685EB9:00D0B3975AC4B799F5BEA16D5E13E9AF971D5E9B984C9F39728B5E5739735A219B97C356436ADC6E95BB0352F6BE64A6C2912D4EF2D0433CED2B6171640012D9460F:015C68226383956E3BD066E797B623C27CE0EAC2F551A10C2C724D9852077B87220B6536C5C408A1D2AEBB8E86D678AE49CB57091F4732296579AB44FCD17F0FC56A:01144C7D79AE6956BC8EDB8E7C787C4521CB086FA64407F97894E5E6B2D79B04D1427E73CA4BAA240A34786859810C06B3C715A3A8CC3151F2BEE417996D19F3DDEA diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index 76e6977a9..e8177e7be 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -7,7 +7,7 @@ depends_on:POLARSSL_ECDH_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C END_DEPENDENCIES BEGIN_CASE -ecdh_primitive_agreement:id +ecdh_primitive_random:id { ecp_group grp; ecp_point qA, qB; @@ -37,3 +37,44 @@ ecdh_primitive_agreement:id mpi_free( &zA ); mpi_free( &zB ); } END_CASE + +BEGIN_CASE +ecdh_primitive_testvec:id:dA:xA:yA:dB:xB:yB:z +{ + ecp_group grp; + ecp_point qA, qB; + mpi dA, dB, zA, zB, check; + + ecp_group_init( &grp ); + ecp_point_init( &qA ); ecp_point_init( &qB ); + mpi_init( &dA ); mpi_init( &dB ); + mpi_init( &zA ); mpi_init( &zB ); mpi_init( &check ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( ecdh_gen_public( &grp, &dA, &qA, ¬_rnd, "{dA}" ) == 0 ); + TEST_ASSERT( ! ecp_is_zero( &qA ) ); + TEST_ASSERT( mpi_read_string( &check, 16, "{xA}" ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &qA.X, &check ) == 0 ); + TEST_ASSERT( mpi_read_string( &check, 16, "{yA}" ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &qA.Y, &check ) == 0 ); + + TEST_ASSERT( ecdh_gen_public( &grp, &dB, &qB, ¬_rnd, "{dB}" ) == 0 ); + TEST_ASSERT( ! ecp_is_zero( &qB ) ); + TEST_ASSERT( mpi_read_string( &check, 16, "{xB}" ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &qB.X, &check ) == 0 ); + TEST_ASSERT( mpi_read_string( &check, 16, "{yB}" ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &qB.Y, &check ) == 0 ); + + TEST_ASSERT( mpi_read_string( &check, 16, "{z}" ) == 0 ); + TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &zA, &check ) == 0 ); + TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &zB, &check ) == 0 ); + + ecp_group_free( &grp ); + ecp_point_free( &qA ); ecp_point_free( &qB ); + mpi_free( &dA ); mpi_free( &dB ); + mpi_free( &zA ); mpi_free( &zB ); mpi_free( &check ); +} +END_CASE diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 08a5e2bc7..db047629d 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -208,15 +208,6 @@ ecp_test_vect:SECP384R1:"D27335EA71664AF244DD14E9FD1260715DFD8A7965571C48D709EE7 ECP test vectors secp521r1 rfc 5114 ecp_test_vect:SECP521R1:"0113F82DA825735E3D97276683B2B74277BAD27335EA71664AF2430CC4F33459B9669EE78B3FFB9B8683015D344DCBFEF6FB9AF4C6C470BE254516CD3C1A1FB47362":"01EBB34DD75721ABF8ADC9DBED17889CBB9765D90A7C60F2CEF007BB0F2B26E14881FD4442E689D61CB2DD046EE30E3FFD20F9A45BBDF6413D583A2DBF59924FD35C":"00F6B632D194C0388E22D8437E558C552AE195ADFD153F92D74908351B2F8C4EDA94EDB0916D1B53C020B5EECAED1A5FC38A233E4830587BB2EE3489B3B42A5A86A4":"00CEE3480D8645A17D249F2776D28BAE616952D1791FDB4B70F7C3378732AA1B22928448BCD1DC2496D435B01048066EBE4F72903C361B1A9DC1193DC2C9D0891B96":"010EBFAFC6E85E08D24BFFFCC1A4511DB0E634BEEB1B6DEC8C5939AE44766201AF6200430BA97C8AC6A0E9F08B33CE7E9FEEB5BA4EE5E0D81510C24295B8A08D0235":"00A4A6EC300DF9E257B0372B5E7ABFEF093436719A77887EBB0B18CF8099B9F4212B6E30A1419C18E029D36863CC9D448F4DBA4D2A0E60711BE572915FBD4FEF2695":"00CDEA89621CFA46B132F9E4CFE2261CDE2D4368EB5656634C7CC98C7A00CDE54ED1866A0DD3E6126C9D2F845DAFF82CEB1DA08F5D87521BB0EBECA77911169C20CC":"00F9A71641029B7FC1A808AD07CD4861E868614B865AFBECAB1F2BD4D8B55EBCB5E3A53143CEB2C511B1AE0AF5AC827F60F2FD872565AC5CA0A164038FE980A7E4BD" -ECP test vectors secp256r1 rfc 5903 -ecp_test_vect:SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"DAD0B65394221CF9B051E1FECA5787D098DFE637FC90B9EF945D0C3772581180":"5271A0461CDB8252D61F1C456FA3E59AB1F45B33ACCF5F58389E0577B8990BB3":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D12DFB5289C8D4F81208B70270398C342296970A0BCCB74C736FC7554494BF63":"56FBF3CA366CC23E8157854C13C58D6AAC23F046ADA30F8353E74F33039872AB":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":"522BDE0AF0D8585B8DEF9C183B5AE38F50235206A8674ECB5D98EDB20EB153A2" - -ECP test vectors secp384r1 rfc 5903 -ecp_test_vect:SECP384R1:"099F3C7034D4A2C699884D73A375A67F7624EF7C6B3C0F160647B67414DCE655E35B538041E649EE3FAEF896783AB194":"667842D7D180AC2CDE6F74F37551F55755C7645C20EF73E31634FE72B4C55EE6DE3AC808ACB4BDB4C88732AEE95F41AA":"9482ED1FC0EEB9CAFC4984625CCFC23F65032149E0E144ADA024181535A0F38EEB9FCFF3C2C947DAE69B4C634573A81C":"41CB0779B4BDB85D47846725FBEC3C9430FAB46CC8DC5060855CC9BDA0AA2942E0308312916B8ED2960E4BD55A7448FC":"E558DBEF53EECDE3D3FCCFC1AEA08A89A987475D12FD950D83CFA41732BC509D0D1AC43A0336DEF96FDA41D0774A3571":"DCFBEC7AACF3196472169E838430367F66EEBE3C6E70C416DD5F0C68759DD1FFF83FA40142209DFF5EAAD96DB9E6386C":"11187331C279962D93D604243FD592CB9D0A926F422E47187521287E7156C5C4D603135569B9E9D09CF5D4A270F59746":"A2A9F38EF5CAFBE2347CF7EC24BDD5E624BC93BFA82771F40D1B65D06256A852C983135D4669F8792F2C1D55718AFBB4" - -ECP test vectors secp521r1 rfc 5903 -ecp_test_vect:SECP521R1:"0037ADE9319A89F4DABDB3EF411AACCCA5123C61ACAB57B5393DCE47608172A095AA85A30FE1C2952C6771D937BA9777F5957B2639BAB072462F68C27A57382D4A52":"0015417E84DBF28C0AD3C278713349DC7DF153C897A1891BD98BAB4357C9ECBEE1E3BF42E00B8E380AEAE57C2D107564941885942AF5A7F4601723C4195D176CED3E":"017CAE20B6641D2EEB695786D8C946146239D099E18E1D5A514C739D7CB4A10AD8A788015AC405D7799DC75E7B7D5B6CF2261A6A7F1507438BF01BEB6CA3926F9582":"0145BA99A847AF43793FDD0E872E7CDFA16BE30FDC780F97BCCC3F078380201E9C677D600B343757A3BDBF2A3163E4C2F869CCA7458AA4A4EFFC311F5CB151685EB9":"00D0B3975AC4B799F5BEA16D5E13E9AF971D5E9B984C9F39728B5E5739735A219B97C356436ADC6E95BB0352F6BE64A6C2912D4EF2D0433CED2B6171640012D9460F":"015C68226383956E3BD066E797B623C27CE0EAC2F551A10C2C724D9852077B87220B6536C5C408A1D2AEBB8E86D678AE49CB57091F4732296579AB44FCD17F0FC56A":"01144C7D79AE6956BC8EDB8E7C787C4521CB086FA64407F97894E5E6B2D79B04D1427E73CA4BAA240A34786859810C06B3C715A3A8CC3151F2BEE417996D19F3DDEA":"01B901E6B17DB2947AC017D853EF1C1674E5CFE59CDA18D078E05D1B5242ADAA9FFC3C63EA05EDB1E13CE5B3A8E50C3EB622E8DA1B38E0BDD1F88569D6C99BAFFA43" - ECP selftest depends_on:POLARSSL_SELF_TEST ecp_selftest: From 450a163c8149dca9ca590e1b8d4c301627375d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 27 Jan 2013 09:08:18 +0100 Subject: [PATCH 57/76] Fix valgrind warning in ECDSA test suite. --- tests/suites/test_suite_ecdsa.function | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index 89f9979a6..d5b21d468 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -19,6 +19,7 @@ ecdsa_random:id ecp_point_init( &Q ); mpi_init( &d ); mpi_init( &r ); mpi_init( &s ); memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + memset( buf, 0, sizeof( buf ) ); /* prepare material for signature */ TEST_ASSERT( rnd_pseudo_rand( &rnd_info, buf, sizeof( buf ) ) == 0 ); @@ -49,6 +50,7 @@ ecdsa_test_vectors:id:d:xQ:yQ:k:hash:r:s ecp_point_init( &Q ); mpi_init( &d ); mpi_init( &r ); mpi_init( &s ); mpi_init( &r_check ); mpi_init( &s_check ); + memset( buf, 0, sizeof( buf ) ); TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); TEST_ASSERT( ecp_point_read_string( &Q, 16, "{xQ}", "{yQ}" ) == 0 ); From cf4a70c8ed53d17180c526f3a02c455448a15be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 27 Jan 2013 09:10:53 +0100 Subject: [PATCH 58/76] Adjust names of ECDSA tests. --- tests/suites/test_suite_ecdsa.data | 32 +++++++++++++------------- tests/suites/test_suite_ecdsa.function | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index 15848bc2e..5a94419f7 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -1,24 +1,24 @@ -ECDSA random sign-verify #1 -ecdsa_random:SECP192R1 +ECDSA primitive random #1 +ecdsa_prim_random:SECP192R1 -ECDSA random sign-verify #2 -ecdsa_random:SECP224R1 +ECDSA primitive random #2 +ecdsa_prim_random:SECP224R1 -ECDSA random sign-verify #3 -ecdsa_random:SECP256R1 +ECDSA primitive random #3 +ecdsa_prim_random:SECP256R1 -ECDSA random sign-verify #4 -ecdsa_random:SECP384R1 +ECDSA primitive random #4 +ecdsa_prim_random:SECP384R1 -ECDSA random sign-verify #5 -ecdsa_random:SECP521R1 +ECDSA primitive random #5 +ecdsa_prim_random:SECP521R1 -ECDSA rfc 4754 p256 -ecdsa_test_vectors:SECP256R1:DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F:2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970:6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D:9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B154BF61AF1D5A6DECE:BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD:CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C:86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315 +ECDSA primitive rfc 4754 p256 +ecdsa_prim_test_vectors:SECP256R1:DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F:2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970:6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D:9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B154BF61AF1D5A6DECE:BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD:CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C:86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315 -ECDSA rfc 4754 p384 -ecdsa_test_vectors:SECP384R1:0BEB646634BA87735D77AE4809A0EBEA865535DE4C1E1DCB692E84708E81A5AF62E528C38B2A81B35309668D73524D9F:96281BF8DD5E0525CA049C048D345D3082968D10FEDF5C5ACA0C64E6465A97EA5CE10C9DFEC21797415710721F437922:447688BA94708EB6E2E4D59F6AB6D7EDFF9301D249FE49C33096655F5D502FAD3D383B91C5E7EDAA2B714CC99D5743CA:B4B74E44D71A13D568003D7489908D564C7761E229C58CBFA18950096EB7463B854D7FA992F934D927376285E63414FA:CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7:FB017B914E29149432D8BAC29A514640B46F53DDAB2C69948084E2930F1C8F7E08E07C9C63F2D21A07DCB56A6AF56EB3:B263A1305E057F984D38726A1B46874109F417BCA112674C528262A40A629AF1CBB9F516CE0FA7D2FF630863A00E8B9F +ECDSA primitive rfc 4754 p384 +ecdsa_prim_test_vectors:SECP384R1:0BEB646634BA87735D77AE4809A0EBEA865535DE4C1E1DCB692E84708E81A5AF62E528C38B2A81B35309668D73524D9F:96281BF8DD5E0525CA049C048D345D3082968D10FEDF5C5ACA0C64E6465A97EA5CE10C9DFEC21797415710721F437922:447688BA94708EB6E2E4D59F6AB6D7EDFF9301D249FE49C33096655F5D502FAD3D383B91C5E7EDAA2B714CC99D5743CA:B4B74E44D71A13D568003D7489908D564C7761E229C58CBFA18950096EB7463B854D7FA992F934D927376285E63414FA:CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1631A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7:FB017B914E29149432D8BAC29A514640B46F53DDAB2C69948084E2930F1C8F7E08E07C9C63F2D21A07DCB56A6AF56EB3:B263A1305E057F984D38726A1B46874109F417BCA112674C528262A40A629AF1CBB9F516CE0FA7D2FF630863A00E8B9F -ECDSA sign rfc 4754 p521 -ecdsa_test_vectors:SECP521R1:0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF5849120597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B375FA1:0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD19052A8:006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEAE643:00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B956C2F:DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F:0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE544320552251:017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F866472660 +ECDSA primitive rfc 4754 p521 +ecdsa_prim_test_vectors:SECP521R1:0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF5849120597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B375FA1:0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD19052A8:006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEAE643:00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B956C2F:DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F:0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE544320552251:017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F866472660 diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index d5b21d468..e7d4900dd 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -7,7 +7,7 @@ depends_on:POLARSSL_ECDSA_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C END_DEPENDENCIES BEGIN_CASE -ecdsa_random:id +ecdsa_prim_random:id { ecp_group grp; ecp_point Q; @@ -38,7 +38,7 @@ ecdsa_random:id END_CASE BEGIN_CASE -ecdsa_test_vectors:id:d:xQ:yQ:k:hash:r:s +ecdsa_prim_test_vectors:id:d:xQ:yQ:k:hash:r:s { ecp_group grp; ecp_point Q; From 1a96728964ccbdd2ea831377e5e8eb71b08359dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 9 Feb 2013 17:03:58 +0100 Subject: [PATCH 59/76] Add function parsing a TLS ECParameters record --- include/polarssl/ecp.h | 37 ++++++++++++++++++++++------ library/ecp.c | 31 +++++++++++++++++++++-- tests/suites/test_suite_ecp.data | 15 +++++++++++ tests/suites/test_suite_ecp.function | 22 +++++++++++++++++ 4 files changed, 96 insertions(+), 9 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index b8b19978b..6c1463637 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -89,12 +89,14 @@ ecp_group; * \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(). + * + * \note The values are taken from RFC 4492's enum NamedCurve. */ -#define POLARSSL_ECP_DP_SECP192R1 0 -#define POLARSSL_ECP_DP_SECP224R1 1 -#define POLARSSL_ECP_DP_SECP256R1 2 -#define POLARSSL_ECP_DP_SECP384R1 3 -#define POLARSSL_ECP_DP_SECP521R1 4 +#define POLARSSL_ECP_DP_SECP192R1 19 +#define POLARSSL_ECP_DP_SECP224R1 21 +#define POLARSSL_ECP_DP_SECP256R1 23 +#define POLARSSL_ECP_DP_SECP384R1 24 +#define POLARSSL_ECP_DP_SECP521R1 25 /** * Maximum bit size of the groups (that is, of N) @@ -120,6 +122,12 @@ ecp_group; #define POLARSSL_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ #define POLARSSL_ECP_PF_COMPRESSED 1 /**< Compressed point format */ +/* + * Some constants from RFC 4492 (ECC for TLS) + */ +#define POLARSSL_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType named_curve */ + + #ifdef __cplusplus extern "C" { #endif @@ -259,6 +267,7 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, */ int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, const unsigned char *buf, size_t ilen ); + /** * \brief Set a group using well-known domain parameters * @@ -269,9 +278,23 @@ int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, * POLARSSL_ERR_MPI_XXX if initialization failed * POLARSSL_ERR_ECP_GENERIC if index is out of range * - * \note Index should be a POLARSSL_ECP_DP_XXX macro. + * \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, size_t index ); +int ecp_use_known_dp( ecp_group *grp, uint16_t index ); + +/** + * \brief Read a group from an ECParameters record + * + * \param grp Destination group + * \param buf Start of input buffer + * \param len Buffer length + * + * \return O 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 Addition: R = P + Q diff --git a/library/ecp.c b/library/ecp.c index b8b0dfc74..0a27df2be 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -29,6 +29,7 @@ * 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 */ #include "polarssl/config.h" @@ -493,7 +494,7 @@ cleanup: /* * Set a group using well-known domain parameters */ -int ecp_use_known_dp( ecp_group *grp, size_t index ) +int ecp_use_known_dp( ecp_group *grp, uint16_t index ) { switch( index ) { @@ -525,7 +526,33 @@ int ecp_use_known_dp( ecp_group *grp, size_t index ) SECP521R1_GX, SECP521R1_GY, SECP521R1_N ) ); } - return( POLARSSL_ERR_ECP_GENERIC ); + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * 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 namedcurve; + + /* + * 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 + */ + namedcurve = 256 * buf[0] + buf[1]; + return ecp_use_known_dp( grp, namedcurve ); } /* diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index db047629d..b875aac00 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -184,6 +184,21 @@ ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ce ECP read binary #6 (non-zero, OK) ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 +ECP read params #1 (record too short) +ecp_read_params:"0313":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 + +ECP read params #2 (bad curve_type) +ecp_read_params:"010013":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 + +ECP read params #3 (unknown curve) +ecp_read_params:"030010":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 + +ECP read params #4 (OK, buffer just fits) +ecp_read_params:"030017":0:256 + +ECP read params #5 (OK, buffer continues) +ecp_read_params:"030018DEAD":0:384 + ECP gen keypair ecp_gen_keypair:SECP192R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 290b786de..443d7a3d0 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -322,6 +322,28 @@ ecp_gen_keypair:id } END_CASE +BEGIN_CASE +ecp_read_params:record:ret:bits +{ + ecp_group grp; + unsigned char buf[10]; + int len, ret; + + ecp_group_init( &grp ); + memset( buf, 0x00, sizeof( buf ) ); + + len = unhexify( buf, {record} ); + + ret = ecp_tls_read_group( &grp, buf, len ); + + TEST_ASSERT( ret == {ret} ); + if( ret == 0) + TEST_ASSERT( mpi_msb( &grp.P ) == {bits} ); + + ecp_group_free( &grp ); +} +END_CASE + BEGIN_CASE ecp_selftest: { From 0079405918f3a0b096fe48fd9a2b6bf41815bcfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 9 Feb 2013 19:00:07 +0100 Subject: [PATCH 60/76] Add functions for read/write ECPoint records --- include/polarssl/ecp.h | 48 ++++++++++++++++++++++++++++++++------ library/ecp.c | 53 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 12 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 6c1463637..59afd63c0 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -33,6 +33,7 @@ * ECP error codes */ #define POLARSSL_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL -0x4F80 /**< The buffer is too small to write to. */ #define POLARSSL_ERR_ECP_GENERIC -0x4F00 /**< Generic ECP error */ /** @@ -117,15 +118,15 @@ ecp_group; #define POLARSSL_ECP_WINDOW_SIZE 7 /**< Maximum NAF width used. */ /* - * Point formats + * 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 constants from RFC 4492 (ECC for TLS) + * Some other constants from RFC 4492 */ -#define POLARSSL_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType named_curve */ +#define POLARSSL_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ #ifdef __cplusplus @@ -239,14 +240,16 @@ int ecp_group_read_string( ecp_group *grp, int radix, * \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 ouput + * \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_GENERIC + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BAD_INPUT_DATA + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL */ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, - size_t *olen, unsigned char *buf, size_t buflen ); + uint8_t *olen, unsigned char *buf, size_t buflen ); /** * \brief Import a point from unsigned binary data @@ -284,7 +287,7 @@ int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, int ecp_use_known_dp( ecp_group *grp, uint16_t index ); /** - * \brief Read a group from an ECParameters record + * \brief Set a group from a TLS ECParameters record * * \param grp Destination group * \param buf Start of input buffer @@ -296,6 +299,37 @@ int ecp_use_known_dp( ecp_group *grp, uint16_t index ); */ int ecp_tls_read_group( ecp_group *grp, const unsigned char *buf, size_t len ); +/** + * \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 + * + * \return O 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 buf Buffer to write to + * \param len 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, unsigned char *buf, size_t buf_len ); + /** * \brief Addition: R = P + Q * diff --git a/library/ecp.c b/library/ecp.c index 0a27df2be..b6c50f6a3 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -186,14 +186,14 @@ cleanup: * Export a point into unsigned binary data (SEC1 2.3.3) */ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, - size_t *olen, unsigned char *buf, size_t buflen ) + uint8_t *olen, unsigned char *buf, size_t buflen ) { int ret; size_t plen; if( format != POLARSSL_ECP_PF_UNCOMPRESSED && format != POLARSSL_ECP_PF_COMPRESSED ) - return( POLARSSL_ERR_ECP_GENERIC ); + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); /* * Common case: P == 0 @@ -201,7 +201,7 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, if( mpi_cmp_int( &P->Z, 0 ) == 0 ) { if( buflen < 1 ) - return( POLARSSL_ERR_ECP_GENERIC ); + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); buf[0] = 0x00; *olen = 1; @@ -216,7 +216,7 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, *olen = 2 * plen + 1; if( buflen < *olen ) - return( POLARSSL_ERR_ECP_GENERIC ); + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); buf[0] = 0x04; MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); @@ -227,7 +227,7 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, *olen = plen + 1; if( buflen < *olen ) - return( POLARSSL_ERR_ECP_GENERIC ); + 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 ) ); @@ -264,6 +264,49 @@ 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; + + /* + * We must have at least two bytes (1 for length, at least of 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 ); + + return ecp_read_binary( grp, pt, POLARSSL_ECP_PF_UNCOMPRESSED, + buf, 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, unsigned char *buf, size_t buf_len ) +{ + /* + * buf_len must be at least one, for our length byte + */ + if( buf_len < 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + return ecp_write_binary( grp, pt, format, buf, buf + 1, buf_len - 1); +} + /* * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi. * See the documentation of struct ecp_group. From d84895dc22d9bd625adaab99521cafdd5c7100de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 10:53:04 +0100 Subject: [PATCH 61/76] Supress 'format' argument to ecp_read_binary. And adjust error codes for ecp_*_binary while at it. --- include/polarssl/ecp.h | 3 +-- library/ecp.c | 20 ++++++++------------ tests/suites/test_suite_ecp.data | 25 +++++++++++-------------- tests/suites/test_suite_ecp.function | 8 +++----- 4 files changed, 23 insertions(+), 33 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 59afd63c0..797390184 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -256,7 +256,6 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, * * \param grp Group to which the point should belong * \param P Point to import - * \param format Point format, must be POLARSSL_ECP_PF_UNCOMPRESSED for now * \param buf Input buffer * \param ilen Actual length of input * @@ -268,7 +267,7 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, * belongs to the given group, see ecp_check_pubkey() for * that. */ -int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, +int ecp_read_binary( const ecp_group *grp, ecp_point *P, const unsigned char *buf, size_t ilen ); /** diff --git a/library/ecp.c b/library/ecp.c index b6c50f6a3..ee0d3fa0b 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -240,25 +240,22 @@ cleanup: /* * Import a point from unsigned binary data (SEC1 2.3.4) */ -int ecp_read_binary( const ecp_group *grp, ecp_point *P, int format, +int ecp_read_binary( const ecp_group *grp, ecp_point *pt, const unsigned char *buf, size_t ilen ) { int ret; size_t plen; - if( format != POLARSSL_ECP_PF_UNCOMPRESSED ) - return( POLARSSL_ERR_ECP_GENERIC ); - if( ilen == 1 && buf[0] == 0x00 ) - return( ecp_set_zero( P ) ); + return( ecp_set_zero( pt ) ); - plen = mpi_size( &grp-> P ); + plen = mpi_size( &grp->P ); if( ilen != 2 * plen + 1 || buf[0] != 0x04 ) - return( POLARSSL_ERR_ECP_GENERIC ); + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - MPI_CHK( mpi_read_binary( &P->X, buf + 1, plen ) ); - MPI_CHK( mpi_read_binary( &P->Y, buf + 1 + plen, plen ) ); - MPI_CHK( mpi_lset( &P->Z, 1 ) ); + 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 ); @@ -285,8 +282,7 @@ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, if( data_len < 1 || data_len > buf_len - 1 ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - return ecp_read_binary( grp, pt, POLARSSL_ECP_PF_UNCOMPRESSED, - buf, data_len ); + return ecp_read_binary( grp, pt, buf, data_len ); } /* diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index b875aac00..9dec01bb1 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -134,55 +134,52 @@ ECP small check pubkey #10 ecp_small_check_pub:10:25:1:POLARSSL_ERR_ECP_GENERIC ECP write binary #0 (zero, bad format) -ecp_write_binary:SECP192R1:"01":"01":"00":UNKNOWN:"00":1:POLARSSL_ERR_ECP_GENERIC +ecp_write_binary:SECP192R1:"01":"01":"00":UNKNOWN:"00":1:POLARSSL_ERR_ECP_BAD_INPUT_DATA ECP write binary #1 (zero, uncompressed, buffer just fits) ecp_write_binary:SECP192R1:"01":"01":"00":UNCOMPRESSED:"00":1:0 ECP write binary #2 (zero, buffer too small) -ecp_write_binary:SECP192R1:"01":"01":"00":UNCOMPRESSED:"00":0:POLARSSL_ERR_ECP_GENERIC +ecp_write_binary:SECP192R1:"01":"01":"00":UNCOMPRESSED:"00":0:POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ECP write binary #3 (non-zero, uncompressed, buffer just fits) ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":UNCOMPRESSED:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":49:0 ECP write binary #4 (non-zero, uncompressed, buffer too small) -ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":UNCOMPRESSED:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":48:POLARSSL_ERR_ECP_GENERIC +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":UNCOMPRESSED:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":48:POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ECP write binary #5 (zero, compressed, buffer just fits) ecp_write_binary:SECP192R1:"01":"01":"00":COMPRESSED:"00":1:0 ECP write binary #6 (zero, buffer too small) -ecp_write_binary:SECP192R1:"01":"01":"00":COMPRESSED:"00":0:POLARSSL_ERR_ECP_GENERIC +ecp_write_binary:SECP192R1:"01":"01":"00":COMPRESSED:"00":0:POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ECP write binary #7 (even, compressed, buffer just fits) ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":COMPRESSED:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0 ECP write binary #8 (even, compressed, buffer too small) -ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":COMPRESSED:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":24:POLARSSL_ERR_ECP_GENERIC +ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":COMPRESSED:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":24:POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ECP write binary #7 (odd, compressed, buffer just fits) ecp_write_binary:SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":COMPRESSED:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0 -ECP read binary #0 (invalid format) -ecp_read_binary:SECP192R1:"00":UNKNOWN:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC - ECP read binary #1 (zero, invalid ilen) -ecp_read_binary:SECP192R1:"0000":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC +ecp_read_binary:SECP192R1:"0000":"01":"01":"00":POLARSSL_ERR_ECP_BAD_INPUT_DATA ECP read binary #2 (zero, invalid first byte) -ecp_read_binary:SECP192R1:"01":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC +ecp_read_binary:SECP192R1:"01":"01":"01":"00":POLARSSL_ERR_ECP_BAD_INPUT_DATA ECP read binary #3 (zero, OK) -ecp_read_binary:SECP192R1:"00":UNCOMPRESSED:"01":"01":"00":0 +ecp_read_binary:SECP192R1:"00":"01":"01":"00":0 ECP read binary #4 (non-zero, invalid ilen) -ecp_read_binary:SECP192R1:"04001122":UNCOMPRESSED:"01":"01":"00":POLARSSL_ERR_ECP_GENERIC +ecp_read_binary:SECP192R1:"04001122":"01":"01":"00":POLARSSL_ERR_ECP_BAD_INPUT_DATA ECP read binary #5 (non-zero, invalid first byte) -ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":POLARSSL_ERR_ECP_GENERIC +ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":POLARSSL_ERR_ECP_BAD_INPUT_DATA ECP read binary #6 (non-zero, OK) -ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 +ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 ECP read params #1 (record too short) ecp_read_params:"0313":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 443d7a3d0..a6694f691 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -230,7 +230,7 @@ ecp_write_binary:id:x:y:z:format:out:blen:ret ecp_group grp; ecp_point P; unsigned char buf[256], str[512]; - size_t olen; + uint8_t olen; memset( buf, 0, sizeof( buf ) ); memset( str, 0, sizeof( str ) ); @@ -258,7 +258,7 @@ ecp_write_binary:id:x:y:z:format:out:blen:ret END_CASE BEGIN_CASE -ecp_read_binary:id:input:format:x:y:z:ret +ecp_read_binary:id:input:x:y:z:ret { ecp_group grp; ecp_point P; @@ -279,9 +279,7 @@ ecp_read_binary:id:input:format:x:y:z:ret ilen = unhexify( buf, {input} ); -#define POLARSSL_ECP_PF_UNKNOWN -1 - TEST_ASSERT( ecp_read_binary( &grp, &P, POLARSSL_ECP_PF_{format}, - buf, ilen ) == {ret} ); + TEST_ASSERT( ecp_read_binary( &grp, &P, buf, ilen ) == {ret} ); if( {ret} == 0 ) { From 7e86025f32da040df148e4ad19dae49f97b95da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 10:58:48 +0100 Subject: [PATCH 62/76] Rename ecp_*_binary to ecp_point_*_binary --- include/polarssl/ecp.h | 9 +++++---- library/ecp.c | 13 +++++++------ tests/suites/test_suite_ecp.function | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 797390184..a810a62dc 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -248,8 +248,9 @@ int ecp_group_read_string( ecp_group *grp, int radix, * or POLARSSL_ERR_ECP_BAD_INPUT_DATA * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL */ -int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, - uint8_t *olen, unsigned char *buf, size_t buflen ); +int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, + int format, uint8_t *olen, + unsigned char *buf, size_t buflen ); /** * \brief Import a point from unsigned binary data @@ -267,8 +268,8 @@ int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, * belongs to the given group, see ecp_check_pubkey() for * that. */ -int ecp_read_binary( const ecp_group *grp, ecp_point *P, - const unsigned char *buf, size_t ilen ); +int ecp_point_read_binary( const ecp_group *grp, ecp_point *P, + const unsigned char *buf, size_t ilen ); /** * \brief Set a group using well-known domain parameters diff --git a/library/ecp.c b/library/ecp.c index ee0d3fa0b..5520d7393 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -185,8 +185,9 @@ cleanup: /* * Export a point into unsigned binary data (SEC1 2.3.3) */ -int ecp_write_binary( const ecp_group *grp, const ecp_point *P, int format, - uint8_t *olen, unsigned char *buf, size_t buflen ) +int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, + int format, uint8_t *olen, + unsigned char *buf, size_t buflen ) { int ret; size_t plen; @@ -240,8 +241,8 @@ cleanup: /* * Import a point from unsigned binary data (SEC1 2.3.4) */ -int ecp_read_binary( const ecp_group *grp, ecp_point *pt, - const unsigned char *buf, size_t ilen ) { +int ecp_point_read_binary( const ecp_group *grp, ecp_point *pt, + const unsigned char *buf, size_t ilen ) { int ret; size_t plen; @@ -282,7 +283,7 @@ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, if( data_len < 1 || data_len > buf_len - 1 ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - return ecp_read_binary( grp, pt, buf, data_len ); + return ecp_point_read_binary( grp, pt, buf, data_len ); } /* @@ -300,7 +301,7 @@ int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt, if( buf_len < 1 ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - return ecp_write_binary( grp, pt, format, buf, buf + 1, buf_len - 1); + return ecp_point_write_binary( grp, pt, format, buf, buf + 1, buf_len - 1); } /* diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index a6694f691..55354ad8b 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -244,7 +244,7 @@ ecp_write_binary:id:x:y:z:format:out:blen:ret TEST_ASSERT( mpi_read_string( &P.Z, 16, {z} ) == 0 ); #define POLARSSL_ECP_PF_UNKNOWN -1 - TEST_ASSERT( ecp_write_binary( &grp, &P, POLARSSL_ECP_PF_{format}, + TEST_ASSERT( ecp_point_write_binary( &grp, &P, POLARSSL_ECP_PF_{format}, &olen, buf, {blen} ) == {ret} ); if( {ret} == 0 ) @@ -279,7 +279,7 @@ ecp_read_binary:id:input:x:y:z:ret ilen = unhexify( buf, {input} ); - TEST_ASSERT( ecp_read_binary( &grp, &P, buf, ilen ) == {ret} ); + TEST_ASSERT( ecp_point_read_binary( &grp, &P, buf, ilen ) == {ret} ); if( {ret} == 0 ) { From 6282acaec22062195fb222589d68afed3bcb98e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 11:15:11 +0100 Subject: [PATCH 63/76] Add basic tests for ecp_tls_*_point --- tests/suites/test_suite_ecp.data | 6 ++ tests/suites/test_suite_ecp.function | 86 +++++++++++++++++++++------- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 9dec01bb1..c2524e3b1 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -181,6 +181,12 @@ ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ce ECP read binary #6 (non-zero, OK) ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 +ECP tls write-read point #1 +ecp_tls_write_read_point:SECP192R1 + +ECP tls write-read point #2 +ecp_tls_write_read_point:SECP521R1 + ECP read params #1 (record too short) ecp_read_params:"0313":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 55354ad8b..d07531c97 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -293,6 +293,70 @@ ecp_read_binary:id:input:x:y:z:ret } END_CASE +BEGIN_CASE +ecp_tls_write_read_point:id +{ + ecp_group grp; + ecp_point pt; + unsigned char buf[256]; + + ecp_group_init( &grp ); + ecp_point_init( &pt ); + memset( buf, 0x00, sizeof( buf ) ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( ecp_tls_write_point( &grp, &grp.G, + POLARSSL_ECP_PF_COMPRESSED, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) + == POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + TEST_ASSERT( ecp_tls_write_point( &grp, &grp.G, + POLARSSL_ECP_PF_UNCOMPRESSED, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &grp.G.X, &pt.X ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &grp.G.Y, &pt.Y ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &grp.G.Z, &pt.Z ) == 0 ); + + TEST_ASSERT( ecp_set_zero( &pt ) == 0 ); + TEST_ASSERT( ecp_tls_write_point( &grp, &pt, + POLARSSL_ECP_PF_COMPRESSED, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_is_zero( &pt ) ); + + TEST_ASSERT( ecp_set_zero( &pt ) == 0 ); + TEST_ASSERT( ecp_tls_write_point( &grp, &pt, + POLARSSL_ECP_PF_UNCOMPRESSED, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_is_zero( &pt ) ); + + ecp_group_free( &grp ); + ecp_point_free( &pt ); +} +END_CASE + +BEGIN_CASE +ecp_read_params:record:ret:bits +{ + ecp_group grp; + unsigned char buf[10]; + int len, ret; + + ecp_group_init( &grp ); + memset( buf, 0x00, sizeof( buf ) ); + + len = unhexify( buf, {record} ); + + ret = ecp_tls_read_group( &grp, buf, len ); + + TEST_ASSERT( ret == {ret} ); + if( ret == 0) + TEST_ASSERT( mpi_msb( &grp.P ) == {bits} ); + + ecp_group_free( &grp ); +} +END_CASE + BEGIN_CASE ecp_gen_keypair:id { @@ -320,28 +384,6 @@ ecp_gen_keypair:id } END_CASE -BEGIN_CASE -ecp_read_params:record:ret:bits -{ - ecp_group grp; - unsigned char buf[10]; - int len, ret; - - ecp_group_init( &grp ); - memset( buf, 0x00, sizeof( buf ) ); - - len = unhexify( buf, {record} ); - - ret = ecp_tls_read_group( &grp, buf, len ); - - TEST_ASSERT( ret == {ret} ); - if( ret == 0) - TEST_ASSERT( mpi_msb( &grp.P ) == {bits} ); - - ecp_group_free( &grp ); -} -END_CASE - BEGIN_CASE ecp_selftest: { From b325887fad0568b5b5b9c4f43e5a5c0fcaae32c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 12:06:19 +0100 Subject: [PATCH 64/76] Add ecp_tls_write_group() --- include/polarssl/ecp.h | 22 +++++++++++++++++++++- library/ecp.c | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index a810a62dc..0919cbe1c 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -53,6 +53,11 @@ typedef struct } ecp_point; +/* + * RFC 4492 defines an enum NamedCurve with two-bytes values + */ +typedef uint16_t ecp_group_id; + /** * \brief ECP group structure * @@ -70,6 +75,7 @@ ecp_point; */ typedef struct { + ecp_group_id id; /*!< RFC 4492 group ID */ mpi P; /*!< prime modulus of the base field */ mpi B; /*!< constant term in the equation */ ecp_point G; /*!< generator of the subgroup used */ @@ -284,7 +290,7 @@ int ecp_point_read_binary( const ecp_group *grp, ecp_point *P, * \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, uint16_t index ); +int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ); /** * \brief Set a group from a TLS ECParameters record @@ -299,6 +305,20 @@ int ecp_use_known_dp( ecp_group *grp, uint16_t index ); */ 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 Import a point from a TLS ECPoint record * diff --git a/library/ecp.c b/library/ecp.c index 5520d7393..41fc9dbac 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -534,9 +534,11 @@ cleanup: /* * Set a group using well-known domain parameters */ -int ecp_use_known_dp( ecp_group *grp, uint16_t index ) +int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) { - switch( index ) + grp->id = id; + + switch( id ) { case POLARSSL_ECP_DP_SECP192R1: grp->modp = ecp_mod_p192; @@ -574,7 +576,7 @@ int ecp_use_known_dp( ecp_group *grp, uint16_t index ) */ int ecp_tls_read_group( ecp_group *grp, const unsigned char *buf, size_t len ) { - uint16_t namedcurve; + ecp_group_id id; /* * We expect at least three bytes (see below) @@ -589,10 +591,37 @@ int ecp_tls_read_group( ecp_group *grp, const unsigned char *buf, size_t len ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); /* - * Next two bytes are the namedcurve + * Next two bytes are the namedcurve value */ - namedcurve = 256 * buf[0] + buf[1]; - return ecp_use_known_dp( grp, namedcurve ); + id = 256 * buf[0] + buf[1]; + return ecp_use_known_dp( 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 ) +{ + /* + * 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] = grp->id >> 8; + buf[1] = grp->id && 0xFF; + + return 0; } /* From 420f1eb675c89afebb7feefb7b2d64c355839921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 12:22:46 +0100 Subject: [PATCH 65/76] Fix ecp_tls_write_point's signature --- include/polarssl/ecp.h | 5 +++-- library/ecp.c | 23 ++++++++++++++++++----- tests/suites/test_suite_ecp.function | 19 ++++++++++--------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 0919cbe1c..373de8d5a 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -255,7 +255,7 @@ int ecp_group_read_string( ecp_group *grp, int radix, * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL */ int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, - int format, uint8_t *olen, + int format, size_t *olen, unsigned char *buf, size_t buflen ); /** @@ -348,7 +348,8 @@ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL */ int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt, - int format, unsigned char *buf, size_t buf_len ); + int format, size_t *olen, + unsigned char *buf, size_t blen ); /** * \brief Addition: R = P + Q diff --git a/library/ecp.c b/library/ecp.c index 41fc9dbac..233c2eba4 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -186,7 +186,7 @@ cleanup: * 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, uint8_t *olen, + int format, size_t *olen, unsigned char *buf, size_t buflen ) { int ret; @@ -293,15 +293,28 @@ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, * } ECPoint; */ int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt, - int format, unsigned char *buf, size_t buf_len ) + int format, size_t *olen, + unsigned char *buf, size_t blen ) { + int ret; + /* - * buf_len must be at least one, for our length byte + * buffer length must be at least one, for our length byte */ - if( buf_len < 1 ) + if( blen < 1 ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - return ecp_point_write_binary( grp, pt, format, buf, buf + 1, buf_len - 1); + 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] = *olen; + ++*olen; + + return 0; } /* diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index d07531c97..bf6104e57 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -230,7 +230,7 @@ ecp_write_binary:id:x:y:z:format:out:blen:ret ecp_group grp; ecp_point P; unsigned char buf[256], str[512]; - uint8_t olen; + size_t olen; memset( buf, 0, sizeof( buf ) ); memset( str, 0, sizeof( str ) ); @@ -299,6 +299,7 @@ ecp_tls_write_read_point:id ecp_group grp; ecp_point pt; unsigned char buf[256]; + size_t olen; ecp_group_init( &grp ); ecp_point_init( &pt ); @@ -307,27 +308,27 @@ ecp_tls_write_read_point:id TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); TEST_ASSERT( ecp_tls_write_point( &grp, &grp.G, - POLARSSL_ECP_PF_COMPRESSED, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) + POLARSSL_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == POLARSSL_ERR_ECP_BAD_INPUT_DATA ); TEST_ASSERT( ecp_tls_write_point( &grp, &grp.G, - POLARSSL_ECP_PF_UNCOMPRESSED, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) == 0 ); + POLARSSL_ECP_PF_UNCOMPRESSED, &olen, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &grp.G.X, &pt.X ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &grp.G.Y, &pt.Y ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &grp.G.Z, &pt.Z ) == 0 ); TEST_ASSERT( ecp_set_zero( &pt ) == 0 ); TEST_ASSERT( ecp_tls_write_point( &grp, &pt, - POLARSSL_ECP_PF_COMPRESSED, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) == 0 ); + POLARSSL_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == 0 ); TEST_ASSERT( ecp_is_zero( &pt ) ); TEST_ASSERT( ecp_set_zero( &pt ) == 0 ); TEST_ASSERT( ecp_tls_write_point( &grp, &pt, - POLARSSL_ECP_PF_UNCOMPRESSED, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, 256 ) == 0 ); + POLARSSL_ECP_PF_UNCOMPRESSED, &olen, buf, 256 ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == 0 ); TEST_ASSERT( ecp_is_zero( &pt ) ); ecp_group_free( &grp ); From 46106a9d754c7a878d85b2e3cf1e541edb8e16a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 12:51:17 +0100 Subject: [PATCH 66/76] Add tests for (and fix bug in) ecp_tls_write_group --- library/ecp.c | 4 +++- tests/suites/test_suite_ecp.data | 26 ++++++++++++++---------- tests/suites/test_suite_ecp.function | 30 +++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 233c2eba4..cc79b7733 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -69,6 +69,8 @@ void ecp_group_init( ecp_group *grp ) if( grp == NULL ) return; + grp->id = 0; + mpi_init( &grp->P ); mpi_init( &grp->B ); ecp_point_init( &grp->G ); @@ -632,7 +634,7 @@ int ecp_tls_write_group( const ecp_group *grp, size_t *olen, * Next two bytes are the namedcurve value */ buf[0] = grp->id >> 8; - buf[1] = grp->id && 0xFF; + buf[1] = grp->id & 0xFF; return 0; } diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index c2524e3b1..e6baf46d2 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -187,20 +187,26 @@ ecp_tls_write_read_point:SECP192R1 ECP tls write-read point #2 ecp_tls_write_read_point:SECP521R1 -ECP read params #1 (record too short) -ecp_read_params:"0313":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 +ECP tls read group #1 (record too short) +ecp_tls_read_group:"0313":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 -ECP read params #2 (bad curve_type) -ecp_read_params:"010013":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 +ECP tls read group #2 (bad curve_type) +ecp_tls_read_group:"010013":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 -ECP read params #3 (unknown curve) -ecp_read_params:"030010":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 +ECP tls read group #3 (unknown curve) +ecp_tls_read_group:"030010":POLARSSL_ERR_ECP_BAD_INPUT_DATA:0 -ECP read params #4 (OK, buffer just fits) -ecp_read_params:"030017":0:256 +ECP tls read group #4 (OK, buffer just fits) +ecp_tls_read_group:"030017":0:256 -ECP read params #5 (OK, buffer continues) -ecp_read_params:"030018DEAD":0:384 +ECP tls read group #5 (OK, buffer continues) +ecp_tls_read_group:"030018DEAD":0:384 + +ECP tls write-read group #1 +ecp_tls_write_read_group:SECP192R1 + +ECP tls write-read group #2 +ecp_tls_write_read_group:SECP521R1 ECP gen keypair ecp_gen_keypair:SECP192R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index bf6104e57..30af8f461 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -337,7 +337,7 @@ ecp_tls_write_read_point:id END_CASE BEGIN_CASE -ecp_read_params:record:ret:bits +ecp_tls_read_group:record:ret:bits { ecp_group grp; unsigned char buf[10]; @@ -358,6 +358,34 @@ ecp_read_params:record:ret:bits } END_CASE +BEGIN_CASE +ecp_tls_write_read_group:id +{ + ecp_group grp1, grp2; + unsigned char buf[10]; + size_t len; + int ret; + + ecp_group_init( &grp1 ); + ecp_group_init( &grp2 ); + memset( buf, 0x00, sizeof( buf ) ); + + TEST_ASSERT( ecp_use_known_dp( &grp1, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( ecp_tls_write_group( &grp1, &len, buf, 10 ) == 0 ); + TEST_ASSERT( ( ret = ecp_tls_read_group( &grp2, buf, len ) ) == 0 ); + + if( ret == 0 ) + { + TEST_ASSERT( mpi_cmp_mpi( &grp1.N, &grp2.N ) == 0 ); + TEST_ASSERT( grp1.id == grp2.id ); + } + + ecp_group_free( &grp1 ); + ecp_group_free( &grp2 ); +} +END_CASE + BEGIN_CASE ecp_gen_keypair:id { From 8c16f96259efadbc4ff4a86f9402409d7c33513d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 13:00:20 +0100 Subject: [PATCH 67/76] Add a few tests for ecp_tls_read_point --- tests/suites/test_suite_ecp.data | 12 ++++++++++ tests/suites/test_suite_ecp.function | 36 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index e6baf46d2..ca71ff338 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -181,6 +181,18 @@ ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ce ECP read binary #6 (non-zero, OK) ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 +ECP tls read point #1 (zero, invalid length byte) +ecp_tls_read_point:SECP192R1:"0200":"01":"01":"00":POLARSSL_ERR_ECP_BAD_INPUT_DATA + +ECP tls read point #2 (zero, OK) +ecp_tls_read_point:SECP192R1:"0100":"01":"01":"00":0 + +ECP tls read point #3 (non-zero, invalid length byte) +ecp_tls_read_point:SECP192R1:"300448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":POLARSSL_ERR_ECP_BAD_INPUT_DATA + +ECP tls read point #4 (non-zero, OK) +ecp_tls_read_point:SECP192R1:"310448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 + ECP tls write-read point #1 ecp_tls_write_read_point:SECP192R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 30af8f461..50de46a86 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -293,6 +293,42 @@ ecp_read_binary:id:input:x:y:z:ret } END_CASE +BEGIN_CASE +ecp_tls_read_point:id:input:x:y:z:ret +{ + ecp_group grp; + ecp_point P; + mpi X, Y, Z; + size_t ilen; + unsigned char buf[256]; + + memset( buf, 0, sizeof( buf ) ); + + ecp_group_init( &grp ); ecp_point_init( &P ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( mpi_read_string( &X, 16, {x} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Y, 16, {y} ) == 0 ); + TEST_ASSERT( mpi_read_string( &Z, 16, {z} ) == 0 ); + + ilen = unhexify( buf, {input} ); + + TEST_ASSERT( ecp_tls_read_point( &grp, &P, buf, ilen ) == {ret} ); + + if( {ret} == 0 ) + { + TEST_ASSERT( mpi_cmp_mpi( &P.X, &X ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &P.Y, &Y ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &P.Z, &Z ) == 0 ); + } + + ecp_group_free( &grp ); ecp_point_free( &P ); + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); +} +END_CASE + BEGIN_CASE ecp_tls_write_read_point:id { From 7c145c64183aa819727faee48993a0cd8b1a1059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 13:20:52 +0100 Subject: [PATCH 68/76] Fix ecp_tls_read_group's signature --- include/polarssl/ecp.h | 4 ++-- library/ecp.c | 8 +++++--- tests/suites/test_suite_ecp.data | 2 +- tests/suites/test_suite_ecp.function | 9 +++++++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 373de8d5a..ec9067dfe 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -296,14 +296,14 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ); * \brief Set a group from a TLS ECParameters record * * \param grp Destination group - * \param buf Start of input buffer + * \param buf &(Start of input buffer) * \param len Buffer length * * \return O 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 ); +int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len ); /** * \brief Write the TLS ECParameters record for a group diff --git a/library/ecp.c b/library/ecp.c index cc79b7733..68f20f7c7 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -589,7 +589,7 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) /* * Set a group from an ECParameters record (RFC 4492) */ -int ecp_tls_read_group( ecp_group *grp, const unsigned char *buf, size_t len ) +int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len ) { ecp_group_id id; @@ -602,13 +602,15 @@ int ecp_tls_read_group( ecp_group *grp, const unsigned char *buf, size_t len ) /* * First byte is curve_type; only named_curve is handled */ - if( *buf++ != POLARSSL_ECP_TLS_NAMED_CURVE ) + if( *(*buf)++ != POLARSSL_ECP_TLS_NAMED_CURVE ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); /* * Next two bytes are the namedcurve value */ - id = 256 * buf[0] + buf[1]; + id = *(*buf)++; + id <<= 8; + id |= *(*buf)++; return ecp_use_known_dp( grp, id ); } diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index ca71ff338..57b3113b5 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -212,7 +212,7 @@ ECP tls read group #4 (OK, buffer just fits) ecp_tls_read_group:"030017":0:256 ECP tls read group #5 (OK, buffer continues) -ecp_tls_read_group:"030018DEAD":0:384 +ecp_tls_read_group:"0300180000":0:384 ECP tls write-read group #1 ecp_tls_write_read_group:SECP192R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 50de46a86..64e014755 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -377,6 +377,7 @@ ecp_tls_read_group:record:ret:bits { ecp_group grp; unsigned char buf[10]; + const unsigned char *vbuf = buf; int len, ret; ecp_group_init( &grp ); @@ -384,11 +385,14 @@ ecp_tls_read_group:record:ret:bits len = unhexify( buf, {record} ); - ret = ecp_tls_read_group( &grp, buf, len ); + ret = ecp_tls_read_group( &grp, &vbuf, len ); TEST_ASSERT( ret == {ret} ); if( ret == 0) + { TEST_ASSERT( mpi_msb( &grp.P ) == {bits} ); + TEST_ASSERT( *vbuf == 0x00 ); + } ecp_group_free( &grp ); } @@ -399,6 +403,7 @@ ecp_tls_write_read_group:id { ecp_group grp1, grp2; unsigned char buf[10]; + const unsigned char *vbuf = buf; size_t len; int ret; @@ -409,7 +414,7 @@ ecp_tls_write_read_group:id TEST_ASSERT( ecp_use_known_dp( &grp1, POLARSSL_ECP_DP_{id} ) == 0 ); TEST_ASSERT( ecp_tls_write_group( &grp1, &len, buf, 10 ) == 0 ); - TEST_ASSERT( ( ret = ecp_tls_read_group( &grp2, buf, len ) ) == 0 ); + TEST_ASSERT( ( ret = ecp_tls_read_group( &grp2, &vbuf, len ) ) == 0 ); if( ret == 0 ) { From 98f51815d6f9b455df60c8ab613f7c976f7fd143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 13:38:29 +0100 Subject: [PATCH 69/76] Fix ecp_tls_read_point's signature --- include/polarssl/ecp.h | 4 ++-- library/ecp.c | 13 ++++++++++--- tests/suites/test_suite_ecp.function | 22 ++++++++++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index ec9067dfe..8debda44a 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -324,7 +324,7 @@ int ecp_tls_write_group( const ecp_group *grp, size_t *olen, * * \param grp ECP group used * \param pt Destination point - * \param buf Start of input buffer + * \param buf $(Start of input buffer) * \param len Buffer length * * \return O if successful, @@ -332,7 +332,7 @@ int ecp_tls_write_group( const ecp_group *grp, size_t *olen, * 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 ); + const unsigned char **buf, size_t len ); /** * \brief Export a point as a TLS ECPoint record diff --git a/library/ecp.c b/library/ecp.c index 68f20f7c7..a76ce7062 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -271,9 +271,10 @@ cleanup: * } ECPoint; */ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, - const unsigned char *buf, size_t buf_len ) + 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 of for data) @@ -281,11 +282,17 @@ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, if( buf_len < 2 ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - data_len = *buf++; + data_len = *(*buf)++; if( data_len < 1 || data_len > buf_len - 1 ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - return ecp_point_read_binary( grp, pt, buf, data_len ); + /* + * 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 ); } /* diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 64e014755..a051bd74d 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -301,6 +301,7 @@ ecp_tls_read_point:id:input:x:y:z:ret mpi X, Y, Z; size_t ilen; unsigned char buf[256]; + const unsigned char *vbuf = buf; memset( buf, 0, sizeof( buf ) ); @@ -315,13 +316,14 @@ ecp_tls_read_point:id:input:x:y:z:ret ilen = unhexify( buf, {input} ); - TEST_ASSERT( ecp_tls_read_point( &grp, &P, buf, ilen ) == {ret} ); + TEST_ASSERT( ecp_tls_read_point( &grp, &P, &vbuf, ilen ) == {ret} ); if( {ret} == 0 ) { TEST_ASSERT( mpi_cmp_mpi( &P.X, &X ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &P.Y, &Y ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &P.Z, &Z ) == 0 ); + TEST_ASSERT( *vbuf == 0x00 ); } ecp_group_free( &grp ); ecp_point_free( &P ); @@ -335,37 +337,45 @@ ecp_tls_write_read_point:id ecp_group grp; ecp_point pt; unsigned char buf[256]; + const unsigned char *vbuf; size_t olen; ecp_group_init( &grp ); ecp_point_init( &pt ); - memset( buf, 0x00, sizeof( buf ) ); TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; TEST_ASSERT( ecp_tls_write_point( &grp, &grp.G, POLARSSL_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + TEST_ASSERT( vbuf == buf + olen ); + memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; TEST_ASSERT( ecp_tls_write_point( &grp, &grp.G, POLARSSL_ECP_PF_UNCOMPRESSED, &olen, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &grp.G.X, &pt.X ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &grp.G.Y, &pt.Y ) == 0 ); TEST_ASSERT( mpi_cmp_mpi( &grp.G.Z, &pt.Z ) == 0 ); + TEST_ASSERT( vbuf == buf + olen ); + memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; TEST_ASSERT( ecp_set_zero( &pt ) == 0 ); TEST_ASSERT( ecp_tls_write_point( &grp, &pt, POLARSSL_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == 0 ); TEST_ASSERT( ecp_is_zero( &pt ) ); + TEST_ASSERT( vbuf == buf + olen ); + memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; TEST_ASSERT( ecp_set_zero( &pt ) == 0 ); TEST_ASSERT( ecp_tls_write_point( &grp, &pt, POLARSSL_ECP_PF_UNCOMPRESSED, &olen, buf, 256 ) == 0 ); - TEST_ASSERT( ecp_tls_read_point( &grp, &pt, buf, olen ) == 0 ); + TEST_ASSERT( ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == 0 ); TEST_ASSERT( ecp_is_zero( &pt ) ); + TEST_ASSERT( vbuf == buf + olen ); ecp_group_free( &grp ); ecp_point_free( &pt ); From 63533e44c25d1d8a131e5a8f04b712ac15236cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 14:21:04 +0100 Subject: [PATCH 70/76] Create ecdh_context structure --- include/polarssl/ecdh.h | 27 +++++++++++++++++++++++++++ library/ecdh.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h index ad131061c..2f1e51dd4 100644 --- a/include/polarssl/ecdh.h +++ b/include/polarssl/ecdh.h @@ -29,6 +29,19 @@ #include "polarssl/ecp.h" +/** + * \brief ECDH context structure + */ +typedef struct +{ + ecp_group grp; /*!< ellipitic curve used */ + mpi d; /*!< our secret value */ + ecp_point Q; /*!< our public value */ + ecp_point Qp; /*!< peer's public value */ + mpi z; /*!< shared secret */ +} +ecdh_context; + #ifdef __cplusplus extern "C" { #endif @@ -63,6 +76,20 @@ int ecdh_gen_public( const ecp_group *grp, mpi *d, ecp_point *Q, int ecdh_compute_shared( const ecp_group *grp, mpi *z, const ecp_point *Q, const mpi *d ); +/** + * \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 Checkup routine * diff --git a/library/ecdh.c b/library/ecdh.c index 1b4fcd3b2..0e2cfdf5b 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -27,6 +27,7 @@ * References: * * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 */ #include "polarssl/config.h" @@ -74,6 +75,34 @@ cleanup: return( ret ); } +/* + * Initialize context + */ +void ecdh_init( ecdh_context *ctx ) +{ + ecp_group_init( &ctx->grp ); + mpi_init ( &ctx->d ); + ecp_point_init( &ctx->Q ); + ecp_point_init( &ctx->Qp ); + mpi_init ( &ctx->z ); +} + + +/* + * Free context + */ +void ecdh_free( ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_group_free( &ctx->grp ); + mpi_free ( &ctx->d ); + ecp_point_free( &ctx->Q ); + ecp_point_free( &ctx->Qp ); + mpi_free ( &ctx->z ); +} + #if defined(POLARSSL_SELF_TEST) From 13724765b27b0456a144df9c3f2bd6a30c4cb35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sun, 10 Feb 2013 15:01:54 +0100 Subject: [PATCH 71/76] Add ecdh_make_server_params (untested yet) --- include/polarssl/ecdh.h | 30 +++++++++++++++++++++++++----- library/ecdh.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h index 2f1e51dd4..992850333 100644 --- a/include/polarssl/ecdh.h +++ b/include/polarssl/ecdh.h @@ -34,11 +34,12 @@ */ typedef struct { - ecp_group grp; /*!< ellipitic curve used */ - mpi d; /*!< our secret value */ - ecp_point Q; /*!< our public value */ - ecp_point Qp; /*!< peer's public value */ - mpi z; /*!< shared secret */ + ecp_group grp; /*!< ellipitic curve used */ + mpi d; /*!< our secret value */ + ecp_point Q; /*!< our public value */ + ecp_point Qp; /*!< peer's public value */ + mpi z; /*!< shared secret */ + int point_format; /*!< format for point export */ } ecdh_context; @@ -90,6 +91,25 @@ void ecdh_init( ecdh_context *ctx ); */ void ecdh_free( ecdh_context *ctx ); +/** + * \brief Setup and write the ServerKeyExhange parameters + * + * \param ctx ECDH context + * \param buf destination buffer + * \param olen number of chars written + * \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_server_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 Checkup routine * diff --git a/library/ecdh.c b/library/ecdh.c index 0e2cfdf5b..32f044a54 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -85,9 +85,9 @@ void ecdh_init( ecdh_context *ctx ) ecp_point_init( &ctx->Q ); ecp_point_init( &ctx->Qp ); mpi_init ( &ctx->z ); + ctx->point_format = POLARSSL_ECP_PF_UNCOMPRESSED; } - /* * Free context */ @@ -103,6 +103,40 @@ void ecdh_free( ecdh_context *ctx ) mpi_free ( &ctx->z ); } +/* + * Setup and write the ServerKeyExhange parameters + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int ecdh_make_server_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( ( 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; +} + #if defined(POLARSSL_SELF_TEST) From 854fbd7ba27eb89b39646e60e1aed8474474e340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 11 Feb 2013 20:28:55 +0100 Subject: [PATCH 72/76] Add ecdh_read_params(). --- include/polarssl/ecdh.h | 20 +++++++++++++---- library/ecdh.c | 31 ++++++++++++++++++++++----- tests/suites/test_suite_ecdh.data | 6 ++++++ tests/suites/test_suite_ecdh.function | 25 +++++++++++++++++++++ 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h index 992850333..6b8a905aa 100644 --- a/include/polarssl/ecdh.h +++ b/include/polarssl/ecdh.h @@ -105,10 +105,22 @@ void ecdh_free( ecdh_context *ctx ); * * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code */ -int ecdh_make_server_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 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 the ServerKeyExhange parameters + * + * \param ctx ECDH context + * \param buf $(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 Checkup routine diff --git a/library/ecdh.c b/library/ecdh.c index 32f044a54..462e0155c 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -104,16 +104,16 @@ void ecdh_free( ecdh_context *ctx ) } /* - * Setup and write the ServerKeyExhange parameters + * Setup and write the ServerKeyExhange parameters (RFC 4492) * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ -int ecdh_make_server_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 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; @@ -137,6 +137,27 @@ int ecdh_make_server_params( ecdh_context *ctx, size_t *olen, 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; +} #if defined(POLARSSL_SELF_TEST) diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data index 0926ed55e..47b68fb59 100644 --- a/tests/suites/test_suite_ecdh.data +++ b/tests/suites/test_suite_ecdh.data @@ -21,3 +21,9 @@ ecdh_primitive_testvec:SECP384R1:099F3C7034D4A2C699884D73A375A67F7624EF7C6B3C0F1 ECDH primitive rfc 5903 p521 ecdh_primitive_testvec:SECP521R1:0037ADE9319A89F4DABDB3EF411AACCCA5123C61ACAB57B5393DCE47608172A095AA85A30FE1C2952C6771D937BA9777F5957B2639BAB072462F68C27A57382D4A52:0015417E84DBF28C0AD3C278713349DC7DF153C897A1891BD98BAB4357C9ECBEE1E3BF42E00B8E380AEAE57C2D107564941885942AF5A7F4601723C4195D176CED3E:017CAE20B6641D2EEB695786D8C946146239D099E18E1D5A514C739D7CB4A10AD8A788015AC405D7799DC75E7B7D5B6CF2261A6A7F1507438BF01BEB6CA3926F9582:0145BA99A847AF43793FDD0E872E7CDFA16BE30FDC780F97BCCC3F078380201E9C677D600B343757A3BDBF2A3163E4C2F869CCA7458AA4A4EFFC311F5CB151685EB9:00D0B3975AC4B799F5BEA16D5E13E9AF971D5E9B984C9F39728B5E5739735A219B97C356436ADC6E95BB0352F6BE64A6C2912D4EF2D0433CED2B6171640012D9460F:015C68226383956E3BD066E797B623C27CE0EAC2F551A10C2C724D9852077B87220B6536C5C408A1D2AEBB8E86D678AE49CB57091F4732296579AB44FCD17F0FC56A:01144C7D79AE6956BC8EDB8E7C787C4521CB086FA64407F97894E5E6B2D79B04D1427E73CA4BAA240A34786859810C06B3C715A3A8CC3151F2BEE417996D19F3DDEA + +ECDH exchange #1 +ecdh_exchange:SECP192R1 + +ECDH exchange #2 +ecdh_exchange:SECP521R1 diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index e8177e7be..837983479 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -78,3 +78,28 @@ ecdh_primitive_testvec:id:dA:xA:yA:dB:xB:yB:z mpi_free( &zA ); mpi_free( &zB ); mpi_free( &check ); } END_CASE + +BEGIN_CASE +ecdh_exchange:id +{ + ecdh_context srv, cli; + unsigned char buf[1000]; + const unsigned char *vbuf; + size_t len; + rnd_pseudo_info rnd_info; + + ecdh_init( &srv ); + ecdh_init( &cli ); + memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + + TEST_ASSERT( ecp_use_known_dp( &srv.grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; + TEST_ASSERT( ecdh_make_params( &srv, &len, buf, 1000, + &rnd_pseudo_rand, &rnd_info ) == 0 ); + TEST_ASSERT( ecdh_read_params( &cli, &vbuf, buf + len ) == 0 ); + + ecdh_free( &srv ); + ecdh_free( &cli ); +} +END_CASE From 5cceb41d2c0c4c968374bea8411485e776f7c0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 11 Feb 2013 21:51:45 +0100 Subject: [PATCH 73/76] Add ecdh_{make,read}_public() --- include/polarssl/ecdh.h | 27 +++++++++++++++++++++++++++ library/ecdh.c | 27 +++++++++++++++++++++++++++ tests/suites/test_suite_ecdh.function | 5 +++++ 3 files changed, 59 insertions(+) diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h index 6b8a905aa..67d1df512 100644 --- a/include/polarssl/ecdh.h +++ b/include/polarssl/ecdh.h @@ -122,6 +122,33 @@ int ecdh_make_params( ecdh_context *ctx, size_t *olen, int ecdh_read_params( ecdh_context *ctx, const unsigned char **buf, const unsigned char *end ); +/** + * \brief Setup and export the client's public value + * + * \param ctx ECDH context + * \param olen number of bytes actually written + * \param buf destination buffer + * \param blen size of destination buffer + * + * \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 import the client's public value + * + * \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 Checkup routine * diff --git a/library/ecdh.c b/library/ecdh.c index 462e0155c..dc585f47e 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -159,6 +159,33 @@ int ecdh_read_params( ecdh_context *ctx, 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( ( 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 ) +{ + return ecp_tls_read_point( &ctx->grp, &ctx->Qp, &buf, blen ); +} + #if defined(POLARSSL_SELF_TEST) /* diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index 837983479..6f2d39937 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -99,6 +99,11 @@ ecdh_exchange:id &rnd_pseudo_rand, &rnd_info ) == 0 ); TEST_ASSERT( ecdh_read_params( &cli, &vbuf, buf + len ) == 0 ); + memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; + TEST_ASSERT( ecdh_make_public( &cli, &len, buf, 1000, + &rnd_pseudo_rand, &rnd_info ) == 0 ); + TEST_ASSERT( ecdh_read_public( &srv, buf, len ) == 0 ); + ecdh_free( &srv ); ecdh_free( &cli ); } From 424fda5d7bbe86c351efd1d45a29b1e6b2a3980c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 11 Feb 2013 22:05:42 +0100 Subject: [PATCH 74/76] Add ecdh_calc_secret() --- include/polarssl/ecdh.h | 13 +++++++++++++ library/ecdh.c | 17 +++++++++++++++++ tests/suites/test_suite_ecdh.function | 6 +++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h index 67d1df512..7f6f4cb28 100644 --- a/include/polarssl/ecdh.h +++ b/include/polarssl/ecdh.h @@ -149,6 +149,19 @@ int ecdh_make_public( ecdh_context *ctx, size_t *olen, int ecdh_read_public( ecdh_context *ctx, const unsigned char *buf, size_t blen ); +/** + * \brief Derive and export the shared secret + * + * \param ctx ECDH context + * \param olen number of bytes written + * \param buf destination buffer + * \param blen buffer length + * + * \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 ); + /** * \brief Checkup routine * diff --git a/library/ecdh.c b/library/ecdh.c index dc585f47e..c04d34c42 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -186,6 +186,23 @@ int ecdh_read_public( ecdh_context *ctx, return ecp_tls_read_point( &ctx->grp, &ctx->Qp, &buf, blen ); } +/* + * Derive and export the shared secret + */ +int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + + if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d ) ) + != 0 ) + return( ret ); + + *olen = mpi_size( &ctx->z ); + return mpi_write_binary( &ctx->z, buf, blen ); +} + + #if defined(POLARSSL_SELF_TEST) /* diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index 6f2d39937..105f99ce0 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -99,11 +99,15 @@ ecdh_exchange:id &rnd_pseudo_rand, &rnd_info ) == 0 ); TEST_ASSERT( ecdh_read_params( &cli, &vbuf, buf + len ) == 0 ); - memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; + memset( buf, 0x00, sizeof( buf ) ); TEST_ASSERT( ecdh_make_public( &cli, &len, buf, 1000, &rnd_pseudo_rand, &rnd_info ) == 0 ); TEST_ASSERT( ecdh_read_public( &srv, buf, len ) == 0 ); + TEST_ASSERT( ecdh_calc_secret( &srv, &len, buf, 1000 ) == 0 ); + TEST_ASSERT( ecdh_calc_secret( &cli, &len, buf, 1000 ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &srv.z, &cli.z ) == 0 ); + ecdh_free( &srv ); ecdh_free( &cli ); } From f35b739dff2b5f34a81b9da2078676eb26865792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 11 Feb 2013 22:12:39 +0100 Subject: [PATCH 75/76] Add a few check for context validity. --- library/ecdh.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/ecdh.c b/library/ecdh.c index c04d34c42..e30ae3a71 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -118,6 +118,9 @@ int ecdh_make_params( ecdh_context *ctx, size_t *olen, 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 ); @@ -149,6 +152,8 @@ int ecdh_read_params( ecdh_context *ctx, { int ret; + ecdh_init( ctx ); + if( ( ret = ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) return( ret ); @@ -169,6 +174,9 @@ int ecdh_make_public( ecdh_context *ctx, size_t *olen, { 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 ); @@ -183,6 +191,9 @@ int ecdh_make_public( ecdh_context *ctx, size_t *olen, int ecdh_read_public( ecdh_context *ctx, const unsigned char *buf, size_t blen ) { + if( ctx == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + return ecp_tls_read_point( &ctx->grp, &ctx->Qp, &buf, blen ); } @@ -194,6 +205,9 @@ int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, { 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 ) ) != 0 ) return( ret ); From d589a0ddb64924a02ca9c2616876e6d1adbe945d Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 13 Mar 2013 16:30:17 +0100 Subject: [PATCH 76/76] Modified Makefiles to include new files and and config.h to PolarSSL standard --- include/polarssl/config.h | 74 +++++++++++++++++++-------------------- library/Makefile | 3 +- tests/Makefile | 9 +++++ 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 362c237d2..fcdce0be6 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -480,6 +480,43 @@ */ #define POLARSSL_DHM_C +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * Requires: POLARSSL_ECP_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 + */ +#define POLARSSL_ECP_C + /** * \def POLARSSL_ENTROPY_C * @@ -830,43 +867,6 @@ */ #define POLARSSL_XTEA_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 - */ -#define POLARSSL_ECP_C - -/** - * \def POLARSSL_ECDH_C - * - * Enable the elliptic curve Diffie-Hellman library. - * - * Module: library/ecdh.c - * Caller: - * - * Requires: POLARSSL_ECP_C - */ -#define POLARSSL_ECDH_C - -/** - * \def POLARSSL_ECDSA_C - * - * Enable the elliptic curve DSA library. - * - * Module: library/ecdsa.c - * Caller: - * - * Requires: POLARSSL_ECP_C - */ -#define POLARSSL_ECDSA_C - /* \} name */ #endif /* config.h */ diff --git a/library/Makefile b/library/Makefile index 6852e95df..c3cd45179 100644 --- a/library/Makefile +++ b/library/Makefile @@ -39,7 +39,8 @@ OBJS= aes.o arc4.o asn1parse.o \ blowfish.o camellia.o \ certs.o cipher.o cipher_wrap.o \ ctr_drbg.o debug.o des.o \ - dhm.o ecp.o \ + dhm.o ecdh.o ecdsa.o \ + ecp.o \ entropy.o entropy_poll.o \ error.o gcm.o havege.o \ md.o md_wrap.o md2.o \ diff --git a/tests/Makefile b/tests/Makefile index be5e09831..08173e114 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -30,6 +30,7 @@ APPS = test_suite_aes test_suite_arc4 \ test_suite_cipher.des test_suite_cipher.null \ test_suite_ctr_drbg test_suite_debug \ test_suite_des test_suite_dhm \ + test_suite_ecdh test_suite_ecdsa \ test_suite_ecp \ test_suite_error test_suite_gcm.decrypt \ test_suite_gcm.decrypt test_suite_hmac_shax \ @@ -128,6 +129,14 @@ test_suite_dhm: test_suite_dhm.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ +test_suite_ecdh: test_suite_ecdh.c ../library/libpolarssl.a + echo " CC $@.c" + $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ + +test_suite_ecdsa: test_suite_ecdsa.c ../library/libpolarssl.a + echo " CC $@.c" + $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ + test_suite_ecp: test_suite_ecp.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@