1 /*
2  *  ECDH with curve-optimized implementation multiplexing
3  *
4  *  Copyright 2016-2018 INRIA and Microsoft Corporation
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  This file is part of Mbed TLS (https://tls.mbed.org)
20  */
21 
22 #include "common.h"
23 
24 #if defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
25 
26 #include <mbedtls/ecdh.h>
27 
28 #if !(defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16))
29 #define KRML_VERIFIED_UINT128
30 #endif
31 
32 #include <Hacl_Curve25519.h>
33 #include <mbedtls/platform_util.h>
34 
35 #include "x25519.h"
36 
37 #include <string.h>
38 
39 /*
40  * Initialize context
41  */
mbedtls_x25519_init(mbedtls_x25519_context * ctx)42 void mbedtls_x25519_init( mbedtls_x25519_context *ctx )
43 {
44     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x25519_context ) );
45 }
46 
47 /*
48  * Free context
49  */
mbedtls_x25519_free(mbedtls_x25519_context * ctx)50 void mbedtls_x25519_free( mbedtls_x25519_context *ctx )
51 {
52     if( ctx == NULL )
53         return;
54 
55     mbedtls_platform_zeroize( ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES );
56     mbedtls_platform_zeroize( ctx->peer_point, MBEDTLS_X25519_KEY_SIZE_BYTES );
57 }
58 
mbedtls_x25519_make_params(mbedtls_x25519_context * ctx,size_t * olen,unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)59 int mbedtls_x25519_make_params( mbedtls_x25519_context *ctx, size_t *olen,
60                         unsigned char *buf, size_t blen,
61                         int( *f_rng )(void *, unsigned char *, size_t),
62                         void *p_rng )
63 {
64     int ret = 0;
65 
66     uint8_t base[MBEDTLS_X25519_KEY_SIZE_BYTES] = {0};
67 
68     if( ( ret = f_rng( p_rng, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ) ) != 0 )
69         return ret;
70 
71     *olen = MBEDTLS_X25519_KEY_SIZE_BYTES + 4;
72     if( blen < *olen )
73         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
74 
75     *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
76     *buf++ = MBEDTLS_ECP_TLS_CURVE25519 >> 8;
77     *buf++ = MBEDTLS_ECP_TLS_CURVE25519 & 0xFF;
78     *buf++ = MBEDTLS_X25519_KEY_SIZE_BYTES;
79 
80     base[0] = 9;
81     Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, base );
82 
83     base[0] = 0;
84     if( memcmp( buf, base, MBEDTLS_X25519_KEY_SIZE_BYTES) == 0 )
85         return MBEDTLS_ERR_ECP_RANDOM_FAILED;
86 
87     return( 0 );
88 }
89 
mbedtls_x25519_read_params(mbedtls_x25519_context * ctx,const unsigned char ** buf,const unsigned char * end)90 int mbedtls_x25519_read_params( mbedtls_x25519_context *ctx,
91                         const unsigned char **buf, const unsigned char *end )
92 {
93     if( end - *buf < MBEDTLS_X25519_KEY_SIZE_BYTES + 1 )
94         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
95 
96     if( ( *(*buf)++ != MBEDTLS_X25519_KEY_SIZE_BYTES ) )
97         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
98 
99     memcpy( ctx->peer_point, *buf, MBEDTLS_X25519_KEY_SIZE_BYTES );
100     *buf += MBEDTLS_X25519_KEY_SIZE_BYTES;
101     return( 0 );
102 }
103 
mbedtls_x25519_get_params(mbedtls_x25519_context * ctx,const mbedtls_ecp_keypair * key,mbedtls_x25519_ecdh_side side)104 int mbedtls_x25519_get_params( mbedtls_x25519_context *ctx, const mbedtls_ecp_keypair *key,
105                                mbedtls_x25519_ecdh_side side )
106 {
107     size_t olen = 0;
108 
109     switch( side ) {
110     case MBEDTLS_X25519_ECDH_THEIRS:
111         return mbedtls_ecp_point_write_binary( &key->grp, &key->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, ctx->peer_point, MBEDTLS_X25519_KEY_SIZE_BYTES );
112     case MBEDTLS_X25519_ECDH_OURS:
113         return mbedtls_mpi_write_binary_le( &key->d, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES );
114     default:
115         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
116     }
117 }
118 
mbedtls_x25519_calc_secret(mbedtls_x25519_context * ctx,size_t * olen,unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)119 int mbedtls_x25519_calc_secret( mbedtls_x25519_context *ctx, size_t *olen,
120                         unsigned char *buf, size_t blen,
121                         int( *f_rng )(void *, unsigned char *, size_t),
122                         void *p_rng )
123 {
124     /* f_rng and p_rng are not used here because this implementation does not
125        need blinding since it has constant trace. */
126     (( void )f_rng);
127     (( void )p_rng);
128 
129     *olen = MBEDTLS_X25519_KEY_SIZE_BYTES;
130 
131     if( blen < *olen )
132         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
133 
134     Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, ctx->peer_point);
135 
136     /* Wipe the DH secret and don't let the peer chose a small subgroup point */
137     mbedtls_platform_zeroize( ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES );
138 
139     if( memcmp( buf, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES) == 0 )
140         return MBEDTLS_ERR_ECP_RANDOM_FAILED;
141 
142     return( 0 );
143 }
144 
mbedtls_x25519_make_public(mbedtls_x25519_context * ctx,size_t * olen,unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)145 int mbedtls_x25519_make_public( mbedtls_x25519_context *ctx, size_t *olen,
146                         unsigned char *buf, size_t blen,
147                         int( *f_rng )(void *, unsigned char *, size_t),
148                         void *p_rng )
149 {
150     int ret = 0;
151     unsigned char base[MBEDTLS_X25519_KEY_SIZE_BYTES] = { 0 };
152 
153     if( ctx == NULL )
154         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
155 
156     if( ( ret = f_rng( p_rng, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ) ) != 0 )
157         return ret;
158 
159     *olen = MBEDTLS_X25519_KEY_SIZE_BYTES + 1;
160     if( blen < *olen )
161         return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
162     *buf++ = MBEDTLS_X25519_KEY_SIZE_BYTES;
163 
164     base[0] = 9;
165     Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, base );
166 
167     base[0] = 0;
168     if( memcmp( buf, base, MBEDTLS_X25519_KEY_SIZE_BYTES ) == 0 )
169         return MBEDTLS_ERR_ECP_RANDOM_FAILED;
170 
171     return( ret );
172 }
173 
mbedtls_x25519_read_public(mbedtls_x25519_context * ctx,const unsigned char * buf,size_t blen)174 int mbedtls_x25519_read_public( mbedtls_x25519_context *ctx,
175                         const unsigned char *buf, size_t blen )
176 {
177     if( blen < MBEDTLS_X25519_KEY_SIZE_BYTES + 1 )
178         return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
179     if( (*buf++ != MBEDTLS_X25519_KEY_SIZE_BYTES) )
180         return(MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
181     memcpy( ctx->peer_point, buf, MBEDTLS_X25519_KEY_SIZE_BYTES );
182     return( 0 );
183 }
184 
185 
186 #endif /* MBEDTLS_ECDH_C && MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */
187