cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ctx_ecdh.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib ECDH Key Exchange Routines *
4 * Copyright Peter Gutmann 2006-2008 *
5 * *
6 ****************************************************************************/
7 
8 #define PKC_CONTEXT /* Indicate that we're working with PKC contexts */
9 #if defined( INC_ALL )
10  #include "crypt.h"
11  #include "context.h"
12 #else
13  #include "crypt.h"
14  #include "context/context.h"
15 #endif /* Compiler-specific includes */
16 
17 /* The ECDH key exchange process is somewhat complex because there are two
18  phases involved for both sides, an "export" and an "import" phase, and
19  they have to be performed in the correct order. The sequence of
20  operations is:
21 
22  A.load: set p, g from fixed or external values
23  x(A) = rand, x s.t. 0 < x < q-1
24 
25  A.export y(A) = g^x(A) mod p error if y != 0 at start
26  output = y(A)
27 
28  B.load read p, g / set p, g from external values
29  x(B) = rand, x s.t. 0 < x < q-1
30 
31  B.import y(A) = input
32  z = y(A)^x(B) mod p
33 
34  B.export y(B) = g^x(B) mod p error if y != 0 at start
35  output = y(B)
36 
37  A.import y(B) = input
38  z = y(B)^x(A) mod p
39 
40  Note that we have to set x when we load p and g because otherwise we'd
41  have to set x(A) on export and x(B) on import, which is tricky since the
42  ECDH code doesn't know whether it's working with A or B */
43 
44 #ifdef USE_ECDH
45 
46 /****************************************************************************
47 * *
48 * Algorithm Self-test *
49 * *
50 ****************************************************************************/
51 
52 /* Perform a pairwise consistency test on a public/private key pair */
53 
55 static BOOLEAN pairwiseConsistencyTest( INOUT CONTEXT_INFO *contextInfoPtr )
56  {
57  CONTEXT_INFO checkContextInfo;
58  PKC_INFO contextData, *pkcInfo = &contextData;
59  PKC_INFO *sourcePkcInfo = contextInfoPtr->ctxPKC;
60  KEYAGREE_PARAMS keyAgreeParams1, keyAgreeParams2;
62  int bnStatus = BN_STATUS, status;
63 
64  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
65 
66  /* The ECDH pairwise check is a bit more complex than the one for the
67  other algorithms because there's no matched public/private key pair,
68  so we have to load a second ECDH key to use for key agreement with
69  the first one */
70  status = staticInitContext( &checkContextInfo, CONTEXT_PKC,
71  getECDHCapability(), &contextData,
72  sizeof( PKC_INFO ), NULL );
73  if( cryptStatusError( status ) )
74  return( FALSE );
75  pkcInfo->curveType = CRYPT_ECCCURVE_P256;
76  CKPTR( BN_copy( &pkcInfo->eccParam_qx, &sourcePkcInfo->eccParam_qx ) );
77  CKPTR( BN_copy( &pkcInfo->eccParam_qy, &sourcePkcInfo->eccParam_qy ) );
78  CKPTR( BN_copy( &pkcInfo->eccParam_d, &sourcePkcInfo->eccParam_d ) );
79  if( bnStatusError( bnStatus ) )
80  {
81  staticDestroyContext( &checkContextInfo );
82  return( getBnStatus( bnStatus ) );
83  }
84 
85  /* Perform the pairwise test using the check key */
86  capabilityInfoPtr = checkContextInfo.capabilityInfo;
87  memset( &keyAgreeParams1, 0, sizeof( KEYAGREE_PARAMS ) );
88  memset( &keyAgreeParams2, 0, sizeof( KEYAGREE_PARAMS ) );
89  status = capabilityInfoPtr->initKeyFunction( &checkContextInfo, NULL, 0 );
90  if( cryptStatusOK( status ) )
91  status = capabilityInfoPtr->encryptFunction( contextInfoPtr,
92  ( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );
93  if( cryptStatusOK( status ) )
94  status = capabilityInfoPtr->encryptFunction( &checkContextInfo,
95  ( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );
96  if( cryptStatusOK( status ) )
97  status = capabilityInfoPtr->decryptFunction( contextInfoPtr,
98  ( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );
99  if( cryptStatusOK( status ) )
100  status = capabilityInfoPtr->decryptFunction( &checkContextInfo,
101  ( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );
102  if( cryptStatusError( status ) || \
103  keyAgreeParams1.wrappedKeyLen != keyAgreeParams2.wrappedKeyLen || \
104  memcmp( keyAgreeParams1.wrappedKey, keyAgreeParams2.wrappedKey,
105  keyAgreeParams1.wrappedKeyLen ) )
106  status = CRYPT_ERROR_FAILED;
107 
108  /* Clean up */
109  staticDestroyContext( &checkContextInfo );
110 
111  return( cryptStatusOK( status ) ? TRUE : FALSE );
112  }
113 
114 #ifndef CONFIG_NO_SELFTEST
115 
116 /* Test the ECDH implementation (re-)using the test key for the ECDSA test,
117  which comes from from X9.62-2005 section L.4.2. Because a lot of the
118  high-level encryption routines don't exist yet, we cheat a bit and
119  set up a dummy encryption context with just enough information for the
120  following code to work */
121 
122 typedef struct {
123  const int qxLen; const BYTE qx[ 32 ];
124  const int qyLen; const BYTE qy[ 32 ];
125  const int dLen; const BYTE d[ 32 ];
126  } ECC_KEY;
127 
128 static const FAR_BSS ECC_KEY ecdhTestKey = {
129  /* qx */
130  32,
131  { 0x59, 0x63, 0x75, 0xE6, 0xCE, 0x57, 0xE0, 0xF2,
132  0x02, 0x94, 0xFC, 0x46, 0xBD, 0xFC, 0xFD, 0x19,
133  0xA3, 0x9F, 0x81, 0x61, 0xB5, 0x86, 0x95, 0xB3,
134  0xEC, 0x5B, 0x3D, 0x16, 0x42, 0x7C, 0x27, 0x4D },
135  32,
136  /* qy */
137  { 0x42, 0x75, 0x4D, 0xFD, 0x25, 0xC5, 0x6F, 0x93,
138  0x9A, 0x79, 0xF2, 0xB2, 0x04, 0x87, 0x6B, 0x3A,
139  0x3A, 0xB1, 0xCE, 0xB2, 0xE4, 0xFF, 0x57, 0x1A,
140  0xBF, 0x4F, 0xBF, 0x36, 0x32, 0x6C, 0x8B, 0x27 },
141  32,
142  /* d */
143  { 0x2C, 0xA1, 0x41, 0x1A, 0x41, 0xB1, 0x7B, 0x24,
144  0xCC, 0x8C, 0x3B, 0x08, 0x9C, 0xFD, 0x03, 0x3F,
145  0x19, 0x20, 0x20, 0x2A, 0x6C, 0x0D, 0xE8, 0xAB,
146  0xB9, 0x7D, 0xF1, 0x49, 0x8D, 0x50, 0xD2, 0xC8 }
147  };
148 
149 CHECK_RETVAL \
150 static int selfTest( void )
151  {
152  CONTEXT_INFO contextInfo;
153  PKC_INFO contextData, *pkcInfo = &contextData;
154  int status;
155 
156  /* Initialise the key components */
157  status = staticInitContext( &contextInfo, CONTEXT_PKC,
158  getECDHCapability(), &contextData,
159  sizeof( PKC_INFO ), NULL );
160  if( cryptStatusError( status ) )
161  return( CRYPT_ERROR_FAILED );
162  pkcInfo->curveType = CRYPT_ECCCURVE_P256;
163  status = importBignum( &pkcInfo->eccParam_qx, ecdhTestKey.qx,
164  ecdhTestKey.qxLen, ECCPARAM_MIN_QX,
166  if( cryptStatusOK( status ) )
167  status = importBignum( &pkcInfo->eccParam_qy, ecdhTestKey.qy,
168  ecdhTestKey.qyLen, ECCPARAM_MIN_QY,
170  if( cryptStatusOK( status ) )
171  status = importBignum( &pkcInfo->eccParam_d, ecdhTestKey.d,
172  ecdhTestKey.dLen, ECCPARAM_MIN_D,
174  if( cryptStatusError( status ) )
175  {
176  staticDestroyContext( &contextInfo );
177  retIntError();
178  }
179 
180  /* Perform the test key exchange on a block of data */
181  status = contextInfo.capabilityInfo->initKeyFunction( &contextInfo, NULL, 0 );
182  if( cryptStatusOK( status ) && \
183  !pairwiseConsistencyTest( &contextInfo ) )
184  status = CRYPT_ERROR_FAILED;
185 
186  /* Clean up */
187  staticDestroyContext( &contextInfo );
188 
189  return( status );
190  }
191 #else
192  #define selfTest NULL
193 #endif /* !CONFIG_NO_SELFTEST */
194 
195 /****************************************************************************
196 * *
197 * ECDH Key Exchange Routines *
198 * *
199 ****************************************************************************/
200 
201 /* Perform phase 1 of ECDH ("export"). We have to append the distinguisher
202  'Fn' to the name since some systems already have 'encrypt' and 'decrypt'
203  in their standard headers */
204 
205 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
206 static int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr,
207  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer,
208  IN_LENGTH_FIXED( sizeof( KEYAGREE_PARAMS ) ) int noBytes )
209  {
210  PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
211  KEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;
212  int status;
213 
214  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
215  assert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );
216 
217  REQUIRES( noBytes == sizeof( KEYAGREE_PARAMS ) );
218  REQUIRES( !BN_is_zero( &pkcInfo->eccParam_qx ) && \
219  !BN_is_zero( &pkcInfo->eccParam_qy ) );
220 
221  /* Q is generated either at keygen time for static ECDH or as a side-
222  effect of the implicit generation of the d value for ephemeral ECDH,
223  so all we have to do is encode it in X9.62 point form to the output */
224  status = exportECCPoint( keyAgreeParams->publicValue, CRYPT_MAX_PKCSIZE,
225  &keyAgreeParams->publicValueLen,
226  &pkcInfo->eccParam_qx, &pkcInfo->eccParam_qy,
227  bitsToBytes( pkcInfo->keySizeBits ) );
228  if( cryptStatusError( status ) )
229  return( status );
230 
231  /* Perform side-channel attack checks if necessary */
232  if( ( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) && \
233  cryptStatusError( calculateBignumChecksum( pkcInfo,
234  CRYPT_ALGO_ECDH ) ) )
235  {
236  return( CRYPT_ERROR_FAILED );
237  }
238  return( CRYPT_OK );
239  }
240 
241 /* Perform phase 2 of ECDH ("import") */
242 
243 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
244 static int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr,
245  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer,
246  IN_LENGTH_FIXED( sizeof( KEYAGREE_PARAMS ) ) int noBytes )
247  {
248  KEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;
249  PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
250  EC_GROUP *ecCTX = pkcInfo->ecCTX;
251  EC_POINT *q = pkcInfo->tmpPoint;
252  BIGNUM *x = &pkcInfo->tmp1, *y = &pkcInfo->tmp2;
253  int bnStatus = BN_STATUS, status;
254 
255  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
256  assert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );
257  assert( isReadPtr( keyAgreeParams->publicValue,
258  keyAgreeParams->publicValueLen ) );
259 
260  REQUIRES( noBytes == sizeof( KEYAGREE_PARAMS ) );
261  REQUIRES( keyAgreeParams->publicValueLen >= MIN_PKCSIZE_ECCPOINT && \
262  keyAgreeParams->publicValueLen < MAX_INTLENGTH_SHORT );
263 
264  /* The other party's Q value will be stored with the key agreement info
265  in X9.62 point form rather than having been read in when we read the
266  ECDH public key */
267  status = importECCPoint( &pkcInfo->eccParam_qx, &pkcInfo->eccParam_qy,
268  keyAgreeParams->publicValue,
269  keyAgreeParams->publicValueLen,
272  bitsToBytes( pkcInfo->keySizeBits ),
273  &pkcInfo->eccParam_p, KEYSIZE_CHECK_ECC );
274  if( cryptStatusError( status ) )
275  return( status );
276 
277  /* Fill in point structure with coordinates from Q. */
279  &pkcInfo->eccParam_qx,
280  &pkcInfo->eccParam_qy,
281  pkcInfo->bnCTX ) );
282  if( bnStatusError( bnStatus ) )
283  return( getBnStatus( bnStatus ) );
284 
285  /* Multiply Q by private key d. */
286  CK( EC_POINT_mul( ecCTX, q, NULL, q, &pkcInfo->eccParam_d,
287  pkcInfo->bnCTX ) );
288  if( bnStatusError( bnStatus ) )
289  return( getBnStatus( bnStatus ) );
290 
291  /* Extract affine coordinates. */
292  CK( EC_POINT_get_affine_coordinates_GFp( ecCTX, q, x, y, pkcInfo->bnCTX ) );
293  if( bnStatusError( bnStatus ) )
294  return( getBnStatus( bnStatus ) );
295 
296  /* Encode the point. This gets rather ugly because the only two
297  protocols that use ECDH, SSL and SSH, both use only the x coordinate
298  rather than the complete point value. In the interests of
299  consistency we return the full point, so it's up to the users of the
300  ECDH capability to extract any sub-components that they need. This
301  isn't so hard to do because of the use of the fixed-length
302  uncompressed format */
303  status = exportECCPoint( keyAgreeParams->wrappedKey, CRYPT_MAX_PKCSIZE,
304  &keyAgreeParams->wrappedKeyLen, x, y,
305  bitsToBytes( pkcInfo->keySizeBits ) );
306  if( cryptStatusError( status ) )
307  return( status );
308 
309  /* Perform side-channel attack checks if necessary */
310  if( ( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) && \
311  cryptStatusError( calculateBignumChecksum( pkcInfo,
312  CRYPT_ALGO_ECDH ) ) )
313  {
314  return( CRYPT_ERROR_FAILED );
315  }
316  return( CRYPT_OK );
317  }
318 
319 /****************************************************************************
320 * *
321 * Key Management *
322 * *
323 ****************************************************************************/
324 
325 /* Load key components into an encryption context */
326 
328 static int initKey( INOUT CONTEXT_INFO *contextInfoPtr,
329  IN_BUFFER_OPT( keyLength ) const void *key,
330  IN_LENGTH_SHORT_OPT const int keyLength )
331  {
332  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
333  assert( ( key == NULL && keyLength == 0 ) || \
334  ( isReadPtr( key, keyLength ) && \
335  keyLength == sizeof( CRYPT_PKCINFO_ECC ) ) );
336 
337  REQUIRES( ( key == NULL && keyLength == 0 ) || \
338  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_ECC ) ) );
339 
340 #ifndef USE_FIPS140
341  /* Load the key component from the external representation into the
342  internal bignums unless we're doing an internal load */
343  if( key != NULL )
344  {
345  PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
346  const CRYPT_PKCINFO_ECC *eccKey = ( CRYPT_PKCINFO_ECC * ) key;
347  int status;
348 
349  contextInfoPtr->flags |= ( eccKey->isPublicKey ) ? \
351  if( eccKey->curveType == CRYPT_ECCCURVE_NONE )
352  {
353  status = importBignum( &pkcInfo->eccParam_p, eccKey->p,
354  bitsToBytes( eccKey->pLen ),
356  NULL, KEYSIZE_CHECK_ECC );
357  if( cryptStatusOK( status ) )
358  status = importBignum( &pkcInfo->eccParam_a, eccKey->a,
359  bitsToBytes( eccKey->aLen ),
361  NULL, KEYSIZE_CHECK_NONE );
362  if( cryptStatusOK( status ) )
363  status = importBignum( &pkcInfo->eccParam_b, eccKey->b,
364  bitsToBytes( eccKey->bLen ),
366  NULL, KEYSIZE_CHECK_NONE );
367  if( cryptStatusOK( status ) )
368  status = importBignum( &pkcInfo->eccParam_gx, eccKey->gx,
369  bitsToBytes( eccKey->gxLen ),
371  NULL, KEYSIZE_CHECK_NONE );
372  if( cryptStatusOK( status ) )
373  status = importBignum( &pkcInfo->eccParam_gy, eccKey->gy,
374  bitsToBytes( eccKey->gyLen ),
376  NULL, KEYSIZE_CHECK_NONE );
377  if( cryptStatusOK( status ) )
378  status = importBignum( &pkcInfo->eccParam_n, eccKey->n,
379  bitsToBytes( eccKey->nLen ),
381  NULL, KEYSIZE_CHECK_NONE );
382  if( cryptStatusError( status ) )
383  return( status );
384  }
385  else
386  {
387  if( eccKey->curveType <= CRYPT_ECCCURVE_NONE || \
388  eccKey->curveType >= CRYPT_ECCCURVE_LAST )
389  return( CRYPT_ARGERROR_STR1 );
390  pkcInfo->curveType = eccKey->curveType;
391  }
392  status = importBignum( &pkcInfo->eccParam_qx, eccKey->qx,
393  bitsToBytes( eccKey->qxLen ),
395  NULL, KEYSIZE_CHECK_NONE );
396  if( cryptStatusOK( status ) )
397  status = importBignum( &pkcInfo->eccParam_qy, eccKey->qy,
398  bitsToBytes( eccKey->qyLen ),
400  NULL, KEYSIZE_CHECK_NONE );
401  if( cryptStatusOK( status ) && !eccKey->isPublicKey )
402  status = importBignum( &pkcInfo->eccParam_d, eccKey->d,
403  bitsToBytes( eccKey->dLen ),
405  NULL, KEYSIZE_CHECK_NONE );
406  contextInfoPtr->flags |= CONTEXT_FLAG_PBO;
407  if( cryptStatusError( status ) )
408  return( status );
409  }
410 #endif /* USE_FIPS140 */
411 
412  /* Complete the key checking and setup */
413  return( initCheckECCkey( contextInfoPtr, TRUE ) );
414  }
415 
416 /* Generate a key into an encryption context */
417 
419 static int generateKey( INOUT CONTEXT_INFO *contextInfoPtr,
421  const int keySizeBits )
422  {
423  int status;
424 
425  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
426 
427  REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \
428  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );
429 
430  status = generateECCkey( contextInfoPtr, keySizeBits );
431  if( cryptStatusOK( status ) &&
432 #ifndef USE_FIPS140
433  ( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&
434 #endif /* USE_FIPS140 */
435  !pairwiseConsistencyTest( contextInfoPtr ) )
436  {
437  DEBUG_DIAG(( "Consistency check of freshly-generated ECDH key "
438  "failed" ));
439  assert( DEBUG_WARN );
440  status = CRYPT_ERROR_FAILED;
441  }
442  return( status );
443  }
444 
445 /****************************************************************************
446 * *
447 * Capability Access Routines *
448 * *
449 ****************************************************************************/
450 
451 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
452  CRYPT_ALGO_ECDH, bitsToBytes( 0 ), "ECDH", 4,
454  selfTest, getDefaultInfo, NULL, NULL, initKey, generateKey, encryptFn, decryptFn
455  };
456 
457 const CAPABILITY_INFO *getECDHCapability( void )
458  {
459  return( &capabilityInfo );
460  }
461 
462 #endif /* USE_ECDH */