1 /****************************************************************************
2 * *
3 * Public Key Read Routines *
4 * Copyright Peter Gutmann 1992-2012 *
5 * *
6 ****************************************************************************/
7
8 #include <stdio.h>
9 #define PKC_CONTEXT /* Indicate that we're working with PKC contexts */
10 #if defined( INC_ALL )
11 #include "context.h"
12 #include "asn1.h"
13 #include "asn1_ext.h"
14 #include "misc_rw.h"
15 #include "pgp.h"
16 #else
17 #include "context/context.h"
18 #include "enc_dec/asn1.h"
19 #include "enc_dec/asn1_ext.h"
20 #include "enc_dec/misc_rw.h"
21 #include "misc/pgp.h"
22 #endif /* Compiler-specific includes */
23
24 /* The DLP algorithms split the key components over the information in the
25 AlgorithmIdentifier and the actual public/private key components, with the
26 (p, q, g) set classed as domain parameters and included in the
27 AlgorithmIdentifier and y being the actual key.
28
29 params = SEQ {
30 p INTEGER,
31 q INTEGER, -- q for DSA
32 g INTEGER, -- g for DSA
33 j INTEGER OPTIONAL, -- X9.42 only
34 validationParams [...] -- X9.42 only
35 }
36
37 key = y INTEGER -- g^x mod p
38
39 For peculiar historical reasons (copying errors and the use of obsolete
40 drafts as reference material) the X9.42 interpretation used in PKIX
41 reverses the second two parameters from FIPS 186 (so it uses p, g, q
42 instead of p, q, g), so when we read/write the parameter information we
43 have to switch the order in which we read the values if the algorithm
44 isn't DSA */
45
46 #define hasReversedParams( cryptAlgo ) \
47 ( ( cryptAlgo ) == CRYPT_ALGO_DH || \
48 ( cryptAlgo ) == CRYPT_ALGO_ELGAMAL )
49
50 #ifdef USE_PKC
51
52 /****************************************************************************
53 * *
54 * Read X.509 Public Keys *
55 * *
56 ****************************************************************************/
57
58 #ifdef USE_INT_ASN1
59
60 /* Read X.509 SubjectPublicKeyInfo public keys:
61
62 SubjectPublicKeyInfo ::= SEQUENCE {
63 algorithm AlgorithmIdentifier,
64 subjectPublicKey BIT STRING
65 } */
66
67 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readRsaSubjectPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)68 static int readRsaSubjectPublicKey( INOUT STREAM *stream,
69 INOUT CONTEXT_INFO *contextInfoPtr,
70 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
71 {
72 CRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;
73 PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
74 int status;
75
76 assert( isWritePtr( stream, sizeof( STREAM ) ) );
77 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
78 assert( isWritePtr( actionFlags, sizeof( int ) ) );
79
80 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
81 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
82
83 /* Clear return value */
84 *actionFlags = ACTION_PERM_NONE;
85
86 /* Read the SubjectPublicKeyInfo header field and parameter data if
87 there's any present. We read the outer wrapper in generic form since
88 it may be context-specific-tagged if it's coming from a keyset (RSA
89 public keys is the one place where PKCS #15 keys differ from X.509
90 ones) or something odd from CRMF */
91 status = readGenericHole( stream, NULL, 8 + MIN_PKCSIZE_THRESHOLD + \
92 RSAPARAM_MIN_E, DEFAULT_TAG );
93 if( cryptStatusOK( status ) )
94 status = readAlgoID( stream, &cryptAlgo, ALGOID_CLASS_PKC );
95 if( cryptStatusError( status ) )
96 return( status );
97 if( cryptAlgo != CRYPT_ALGO_RSA )
98 return( CRYPT_ERROR_BADDATA );
99
100 /* Set the maximum permitted actions. More restrictive permissions may
101 be set by higher-level code if required and in particular if the key
102 is a pure public key rather than merely the public portions of a
103 private key then the actions will be restricted at that point to
104 encrypt and signature-check only */
105 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \
106 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL ) | \
107 MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL ) | \
108 MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
109
110 /* Read the BIT STRING encapsulation and the public key fields */
111 readBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );
112 readSequence( stream, NULL );
113 status = readBignumChecked( stream, &rsaKey->rsaParam_n,
114 RSAPARAM_MIN_N, RSAPARAM_MAX_N, NULL );
115 if( cryptStatusOK( status ) )
116 status = readBignum( stream, &rsaKey->rsaParam_e,
117 RSAPARAM_MIN_E, RSAPARAM_MAX_E,
118 &rsaKey->rsaParam_n );
119 if( cryptStatusError( status ) )
120 return( status );
121
122 ENSURES( sanityCheckPKCInfo( rsaKey ) );
123
124 return( CRYPT_OK );
125 }
126
127 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readDlpSubjectPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)128 static int readDlpSubjectPublicKey( INOUT STREAM *stream,
129 INOUT CONTEXT_INFO *contextInfoPtr,
130 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
131 {
132 PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;
133 CRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;
134 int extraLength DUMMY_INIT, status;
135
136 assert( isWritePtr( stream, sizeof( STREAM ) ) );
137 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
138 assert( isWritePtr( actionFlags, sizeof( int ) ) );
139
140 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
141 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH || \
142 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
143 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );
144
145 /* Clear return value */
146 *actionFlags = ACTION_PERM_NONE;
147
148 /* Read the SubjectPublicKeyInfo header field and make sure that the DLP
149 parameter data is present */
150 status = readGenericHole( stream, NULL,
151 8 + MIN_PKCSIZE_THRESHOLD + DLPPARAM_MIN_G + \
152 DLPPARAM_MIN_Q + MIN_PKCSIZE_THRESHOLD,
153 DEFAULT_TAG );
154 if( cryptStatusOK( status ) )
155 status = readAlgoIDparam( stream, &cryptAlgo, &extraLength,
156 ALGOID_CLASS_PKC );
157 if( cryptStatusError( status ) )
158 return( status );
159 if( extraLength < MIN_PKCSIZE_THRESHOLD + DLPPARAM_MIN_G + \
160 DLPPARAM_MIN_Q || \
161 extraLength > MAX_INTLENGTH_SHORT )
162 return( CRYPT_ERROR_BADDATA );
163 if( contextInfoPtr->capabilityInfo->cryptAlgo != cryptAlgo )
164 return( CRYPT_ERROR_BADDATA );
165
166 /* Read the header and key parameters */
167 readSequence( stream, NULL );
168 status = readBignumChecked( stream, &dlpKey->dlpParam_p,
169 DLPPARAM_MIN_P, DLPPARAM_MAX_P, NULL );
170 if( cryptStatusError( status ) )
171 return( status );
172 if( hasReversedParams( cryptAlgo ) )
173 {
174 status = readBignum( stream, &dlpKey->dlpParam_g, DLPPARAM_MIN_G,
175 DLPPARAM_MAX_G, &dlpKey->dlpParam_p );
176 if( cryptStatusOK( status ) )
177 status = readBignum( stream, &dlpKey->dlpParam_q, DLPPARAM_MIN_Q,
178 DLPPARAM_MAX_Q, &dlpKey->dlpParam_p );
179 }
180 else
181 {
182 status = readBignum( stream, &dlpKey->dlpParam_q, DLPPARAM_MIN_Q,
183 DLPPARAM_MAX_Q, &dlpKey->dlpParam_p );
184 if( cryptStatusOK( status ) )
185 status = readBignum( stream, &dlpKey->dlpParam_g, DLPPARAM_MIN_G,
186 DLPPARAM_MAX_G, &dlpKey->dlpParam_p );
187 }
188 if( cryptStatusError( status ) )
189 return( status );
190
191 /* Set the maximum permitted actions. Because of the special-case data
192 formatting requirements for DLP algorithms we make the usage
193 internal-only. If the key is a pure public key rather than merely
194 the public portions of a private key then the actions will be
195 restricted by higher-level code to encrypt/signature-check only */
196 if( cryptAlgo == CRYPT_ALGO_DSA )
197 {
198 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
199 ACTION_PERM_NONE_EXTERNAL ) | \
200 MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
201 ACTION_PERM_NONE_EXTERNAL );
202 }
203 else
204 {
205 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
206 ACTION_PERM_NONE_EXTERNAL ) | \
207 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
208 ACTION_PERM_NONE_EXTERNAL );
209 }
210
211 /* Read the BIT STRING encapsulation and the public key fields */
212 readBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );
213 status = readBignumChecked( stream, &dlpKey->dlpParam_y,
214 DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,
215 &dlpKey->dlpParam_p );
216 if( cryptStatusError( status ) )
217 return( status );
218
219 ENSURES( sanityCheckPKCInfo( dlpKey ) );
220
221 return( CRYPT_OK );
222 }
223
224 #if defined( USE_ECDH ) || defined( USE_ECDSA )
225
226 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readEccSubjectPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)227 static int readEccSubjectPublicKey( INOUT STREAM *stream,
228 INOUT CONTEXT_INFO *contextInfoPtr,
229 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
230 {
231 PKC_INFO *eccKey = contextInfoPtr->ctxPKC;
232 CRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;
233 CRYPT_ECCCURVE_TYPE curveType;
234 BYTE buffer[ MAX_PKCSIZE_ECCPOINT + 8 ];
235 int fieldSize DUMMY_INIT;
236 int length, extraLength DUMMY_INIT, status;
237
238 assert( isWritePtr( stream, sizeof( STREAM ) ) );
239 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
240 assert( isWritePtr( actionFlags, sizeof( int ) ) );
241
242 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
243 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDSA );
244
245 /* Clear return value */
246 *actionFlags = ACTION_PERM_NONE;
247
248 /* Read the SubjectPublicKeyInfo header field and make sure that the ECC
249 parameter data is present. Because of the more or less arbitrary
250 manner in which these parameters can be represented we have to be
251 fairly open-ended in terms of the data size limits that we use, and
252 in particular for named curves the lower bound is the size of a
253 single OID that defines the curve */
254 status = readGenericHole( stream, NULL,
255 8 + MIN_OID_SIZE + \
256 MIN_PKCSIZE_ECCPOINT_THRESHOLD,
257 DEFAULT_TAG );
258 if( cryptStatusOK( status ) )
259 status = readAlgoIDparam( stream, &cryptAlgo, &extraLength,
260 ALGOID_CLASS_PKC );
261 if( cryptStatusError( status ) )
262 return( status );
263 if( extraLength < MIN_OID_SIZE || extraLength > MAX_INTLENGTH_SHORT )
264 return( CRYPT_ERROR_BADDATA );
265 if( contextInfoPtr->capabilityInfo->cryptAlgo != cryptAlgo )
266 return( CRYPT_ERROR_BADDATA );
267
268 /* Now things get messy, since the ECC standards authors carefully
269 sidestepped having to make a decision about anything and instead
270 just created an open framework into which it's possible to drop
271 almost anything. To keep things sane we require the use of named
272 curves (which most people seem to use) over a prime field */
273 status = readECCOID( stream, &curveType );
274 if( cryptStatusOK( status ) )
275 status = getECCFieldSize( curveType, &fieldSize, FALSE );
276 if( cryptStatusError( status ) )
277 return( status );
278 eccKey->curveType = curveType;
279
280 /* Set the maximum permitted actions. Because of the special-case data
281 formatting requirements for ECC algorithms (which are a part of the
282 DLP algorithm family) we make the usage internal-only. If the key is
283 a pure public key rather than merely the public portions of a private
284 key then the actions will be restricted by higher-level code to
285 encrypt/signature-check only */
286 if( cryptAlgo == CRYPT_ALGO_ECDSA )
287 {
288 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
289 ACTION_PERM_NONE_EXTERNAL ) | \
290 MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
291 ACTION_PERM_NONE_EXTERNAL );
292 }
293 else
294 {
295 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
296 ACTION_PERM_NONE_EXTERNAL ) | \
297 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
298 ACTION_PERM_NONE_EXTERNAL );
299 }
300
301 /* Read the BIT STRING encapsulation and the public key fields. Instead
302 of encoding the necessary information as an obvious OID + SEQUENCE
303 combination for the parameters it's all stuffed into an ad-hoc BIT
304 STRING that we have to pick apart manually. Note that we can't use
305 the ECC p value for a range check because it hasn't been set yet, all
306 that we have at this point is a curve ID */
307 status = readBitStringHole( stream, &length,
308 MIN_PKCSIZE_ECCPOINT_THRESHOLD, DEFAULT_TAG );
309 if( cryptStatusError( status ) )
310 return( status );
311 if( length < MIN_PKCSIZE_ECCPOINT_THRESHOLD || \
312 length > MAX_PKCSIZE_ECCPOINT )
313 return( CRYPT_ERROR_BADDATA );
314 status = sread( stream, buffer, length );
315 if( cryptStatusError( status ) )
316 return( status );
317 status = importECCPoint( &eccKey->eccParam_qx, &eccKey->eccParam_qy,
318 buffer, length, MIN_PKCSIZE_ECC_THRESHOLD,
319 CRYPT_MAX_PKCSIZE_ECC, fieldSize, NULL,
320 KEYSIZE_CHECK_ECC );
321 zeroise( buffer, length );
322 if( cryptStatusError( status ) )
323 return( status );
324
325 ENSURES( sanityCheckPKCInfo( eccKey ) );
326
327 return( CRYPT_OK );
328 }
329 #endif /* USE_ECDH || USE_ECDSA */
330 #endif /* USE_INT_ASN1 */
331
332 /****************************************************************************
333 * *
334 * Read SSH Public Keys *
335 * *
336 ****************************************************************************/
337
338 #ifdef USE_SSH
339
340 /* Read SSHv2 public keys:
341
342 RSA/DSA:
343
344 string [ server key/certificate ]
345 string "ssh-rsa" "ssh-dss"
346 mpint e p
347 mpint n q
348 mpint g
349 mpint y
350
351 ECDSA:
352
353 string [ server key/certificate ]
354 string "ecdsa-sha2-*"
355 string "*" -- The "*" portion from the above field
356 string Q */
357
358 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readSshRsaPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)359 static int readSshRsaPublicKey( INOUT STREAM *stream,
360 INOUT CONTEXT_INFO *contextInfoPtr,
361 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
362 {
363 PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
364 char buffer[ 16 + 8 ];
365 int length, status;
366
367 assert( isWritePtr( stream, sizeof( STREAM ) ) );
368 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
369 assert( isWritePtr( actionFlags, sizeof( int ) ) );
370
371 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
372 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
373
374 /* Clear return value */
375 *actionFlags = ACTION_PERM_NONE;
376
377 /* Read the wrapper and make sure that it's OK */
378 readUint32( stream );
379 status = readString32( stream, buffer, 7, &length );
380 if( cryptStatusError( status ) )
381 return( status );
382 if( length != 7 || memcmp( buffer, "ssh-rsa", 7 ) )
383 return( CRYPT_ERROR_BADDATA );
384
385 /* Set the maximum permitted actions. SSH keys are only used internally
386 so we restrict the usage to internal-only */
387 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
388 ACTION_PERM_NONE_EXTERNAL );
389
390 /* Read the SSH public key information */
391 status = readBignumInteger32( stream, &rsaKey->rsaParam_e,
392 RSAPARAM_MIN_E, RSAPARAM_MAX_E,
393 NULL );
394 if( cryptStatusOK( status ) )
395 status = readBignumInteger32Checked( stream, &rsaKey->rsaParam_n,
396 RSAPARAM_MIN_N, RSAPARAM_MAX_N );
397 if( cryptStatusError( status ) )
398 return( status );
399
400 ENSURES( sanityCheckPKCInfo( rsaKey ) );
401
402 return( CRYPT_OK );
403 }
404
405 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readSshDlpPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)406 static int readSshDlpPublicKey( INOUT STREAM *stream,
407 INOUT CONTEXT_INFO *contextInfoPtr,
408 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
409 {
410 PKC_INFO *dsaKey = contextInfoPtr->ctxPKC;
411 const BOOLEAN isDH = \
412 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH );
413 char buffer[ 16 + 8 ];
414 int length, status;
415
416 assert( isWritePtr( stream, sizeof( STREAM ) ) );
417 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
418 assert( isWritePtr( actionFlags, sizeof( int ) ) );
419
420 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
421 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH || \
422 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA ) );
423
424 /* Clear return value */
425 *actionFlags = ACTION_PERM_NONE;
426
427 /* Read the wrapper and make sure that it's OK. SSHv2 uses PKCS #3
428 rather than X9.42-style DH keys so we have to treat this algorithm
429 type specially */
430 readUint32( stream );
431 if( isDH )
432 {
433 status = readString32( stream, buffer, 6, &length );
434 if( cryptStatusError( status ) )
435 return( status );
436 if( length != 6 || memcmp( buffer, "ssh-dh", 6 ) )
437 return( CRYPT_ERROR_BADDATA );
438
439 /* Set the maximum permitted actions. SSH keys are only used
440 internally so we restrict the usage to internal-only. Since DH
441 keys can be both public and private keys we allow both usage
442 types even though technically it's a public key */
443 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
444 ACTION_PERM_NONE_EXTERNAL ) | \
445 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
446 ACTION_PERM_NONE_EXTERNAL );
447
448 /* Read the SSH public key information */
449 status = readBignumInteger32Checked( stream, &dsaKey->dlpParam_p,
450 DLPPARAM_MIN_P, DLPPARAM_MAX_P );
451 if( cryptStatusOK( status ) )
452 status = readBignumInteger32( stream, &dsaKey->dlpParam_g,
453 DLPPARAM_MIN_G, DLPPARAM_MAX_G,
454 &dsaKey->dlpParam_p );
455 return( status );
456 }
457
458 /* It's a standard DLP key, read the wrapper and make sure that it's
459 OK */
460 status = readString32( stream, buffer, 7, &length );
461 if( cryptStatusError( status ) )
462 return( status );
463 if( length != 7 || memcmp( buffer, "ssh-dss", 7 ) )
464 return( CRYPT_ERROR_BADDATA );
465
466 /* Set the maximum permitted actions. SSH keys are only used internally
467 so we restrict the usage to internal-only */
468 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
469 ACTION_PERM_NONE_EXTERNAL );
470
471 /* Read the SSH public key information */
472 status = readBignumInteger32Checked( stream, &dsaKey->dlpParam_p,
473 DLPPARAM_MIN_P, DLPPARAM_MAX_P );
474 if( cryptStatusOK( status ) )
475 status = readBignumInteger32( stream, &dsaKey->dlpParam_q,
476 DLPPARAM_MIN_Q, DLPPARAM_MAX_Q,
477 &dsaKey->dlpParam_p );
478 if( cryptStatusOK( status ) )
479 status = readBignumInteger32( stream, &dsaKey->dlpParam_g,
480 DLPPARAM_MIN_G, DLPPARAM_MAX_G,
481 &dsaKey->dlpParam_p );
482 if( cryptStatusOK( status ) && !isDH )
483 status = readBignumInteger32( stream, &dsaKey->dlpParam_y,
484 DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,
485 &dsaKey->dlpParam_p );
486 if( cryptStatusError( status ) )
487 return( status );
488
489 ENSURES( sanityCheckPKCInfo( dsaKey ) );
490
491 return( CRYPT_OK );
492 }
493
494 #if defined( USE_ECDH ) || defined( USE_ECDSA )
495
496 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readSshEccPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)497 static int readSshEccPublicKey( INOUT STREAM *stream,
498 INOUT CONTEXT_INFO *contextInfoPtr,
499 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
500 {
501 PKC_INFO *eccKey = contextInfoPtr->ctxPKC;
502 const BOOLEAN isECDH = \
503 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDH );
504 BYTE buffer[ MAX_PKCSIZE_ECCPOINT + 8 ];
505 int length, fieldSize, status;
506
507 assert( isWritePtr( stream, sizeof( STREAM ) ) );
508 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
509 assert( isWritePtr( actionFlags, sizeof( int ) ) );
510
511 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
512 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDSA );
513
514 /* Clear return value */
515 *actionFlags = ACTION_PERM_NONE;
516
517 /* Set the maximum permitted actions. SSH keys are only used
518 internally so we restrict the usage to internal-only. Since ECDH
519 keys can be both public and private keys we allow both usage
520 types even though technically it's a public key */
521 if( isECDH )
522 {
523 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
524 ACTION_PERM_NONE_EXTERNAL ) | \
525 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
526 ACTION_PERM_NONE_EXTERNAL );
527 }
528 else
529 {
530 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
531 ACTION_PERM_NONE_EXTERNAL );
532 }
533
534 /* Read the wrapper and make sure that it's OK. The key parameter
535 information is repeated twice, so for the overall wrapper we only
536 check for the ECDH/ECDSA algorithm indication and get the parameter
537 information from the second version, which contains only the
538 parameter string */
539 readUint32( stream );
540 status = readString32( stream, buffer, CRYPT_MAX_TEXTSIZE, &length );
541 if( cryptStatusError( status ) )
542 return( status );
543 if( length < 18 ) /* "ecdh-sha2-nistXXXX" */
544 return( CRYPT_ERROR_BADDATA );
545 if( isECDH )
546 {
547 if( memcmp( buffer, "ecdh-sha2-", 10 ) )
548 return( CRYPT_ERROR_BADDATA );
549 }
550 else
551 {
552 if( memcmp( buffer, "ecdsa-sha2-", 11 ) )
553 return( CRYPT_ERROR_BADDATA );
554 }
555
556 /* Read and process the parameter information. At this point we know
557 that we've got valid ECC key data, so if we find anything unexpected
558 we report it as an unavailable ECC field size rather than bad data */
559 status = readString32( stream, buffer, CRYPT_MAX_TEXTSIZE, &length );
560 if( cryptStatusError( status ) )
561 return( status );
562 if( length != 8 ) /* "nistXXXX" */
563 return( CRYPT_ERROR_NOTAVAIL );
564 if( !memcmp( buffer, "nistp256", 8 ) )
565 eccKey->curveType = CRYPT_ECCCURVE_P256;
566 else
567 {
568 if( !memcmp( buffer, "nistp384", 8 ) )
569 eccKey->curveType = CRYPT_ECCCURVE_P384;
570 else
571 {
572 if( !memcmp( buffer, "nistp521", 8 ) )
573 eccKey->curveType = CRYPT_ECCCURVE_P521;
574 else
575 return( CRYPT_ERROR_NOTAVAIL );
576 }
577 }
578 status = getECCFieldSize( eccKey->curveType, &fieldSize, FALSE );
579 if( cryptStatusError( status ) )
580 return( status );
581
582 /* Read the ECC public key. See the comments in
583 readEccSubjectPublicKey() for why the checks are done the way they
584 are */
585 status = readString32( stream, buffer, MAX_PKCSIZE_ECCPOINT, &length );
586 if( cryptStatusError( status ) )
587 return( status );
588 if( length < MIN_PKCSIZE_ECCPOINT_THRESHOLD || \
589 length > MAX_PKCSIZE_ECCPOINT )
590 return( CRYPT_ERROR_BADDATA );
591 status = importECCPoint( &eccKey->eccParam_qx, &eccKey->eccParam_qy,
592 buffer, length, MIN_PKCSIZE_ECC_THRESHOLD,
593 CRYPT_MAX_PKCSIZE_ECC, fieldSize, NULL,
594 KEYSIZE_CHECK_ECC );
595 zeroise( buffer, length );
596 if( cryptStatusError( status ) )
597 return( status );
598
599 ENSURES( sanityCheckPKCInfo( eccKey ) );
600
601 return( CRYPT_OK );
602 }
603 #endif /* USE_ECDH || USE_ECDSA */
604 #endif /* USE_SSH */
605
606 /****************************************************************************
607 * *
608 * Read SSL Public Keys *
609 * *
610 ****************************************************************************/
611
612 #ifdef USE_SSL
613
614 /* Read SSL public keys:
615
616 DH:
617 uint16 dh_pLen
618 byte[] dh_p
619 uint16 dh_gLen
620 byte[] dh_g
621 [ uint16 dh_YsLen ]
622 [ byte[] dh_Ys ]
623
624 ECDH:
625 byte curveType
626 uint16 namedCurve
627 [ uint8 ecPointLen -- NB uint8 not uint16 ]
628 [ byte[] ecPoint ]
629
630 The DH y value is nominally attached to the DH p and g values but isn't
631 processed at this level since this is a pure PKCS #3 DH key and not a
632 generic DLP key. The same holds for the ECDH Q value */
633
634 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readSslDlpPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)635 static int readSslDlpPublicKey( INOUT STREAM *stream,
636 INOUT CONTEXT_INFO *contextInfoPtr,
637 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
638 {
639 PKC_INFO *dhKey = contextInfoPtr->ctxPKC;
640 int status;
641
642 assert( isWritePtr( stream, sizeof( STREAM ) ) );
643 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
644 assert( isWritePtr( actionFlags, sizeof( int ) ) );
645
646 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
647 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH );
648
649 /* Clear return value */
650 *actionFlags = ACTION_PERM_NONE;
651
652 /* Set the maximum permitted actions. SSL keys are only used
653 internally so we restrict the usage to internal-only. Since DH
654 keys can be both public and private keys we allow both usage
655 types even though technically it's a public key */
656 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
657 ACTION_PERM_NONE_EXTERNAL ) | \
658 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
659 ACTION_PERM_NONE_EXTERNAL );
660
661 /* Read the SSL public key information */
662 status = readBignumInteger16UChecked( stream, &dhKey->dlpParam_p,
663 DLPPARAM_MIN_P, DLPPARAM_MAX_P );
664 if( cryptStatusOK( status ) )
665 status = readBignumInteger16U( stream, &dhKey->dlpParam_g,
666 DLPPARAM_MIN_G, DLPPARAM_MAX_G,
667 &dhKey->dlpParam_p );
668 if( cryptStatusError( status ) )
669 return( status );
670
671 ENSURES( sanityCheckPKCInfo( dhKey ) );
672
673 return( CRYPT_OK );
674 }
675
676 #if defined( USE_ECDH )
677
678 static const MAP_TABLE sslCurveInfo[] = {
679 { /* TLS_CURVE_SECP256R1 */ 23, CRYPT_ECCCURVE_P256 },
680 { /* TLS_CURVE_SECP384R1 */ 24, CRYPT_ECCCURVE_P384 },
681 { /* TLS_CURVE_SECP521R1 */ 25, CRYPT_ECCCURVE_P521 },
682 { /* TLS_CURVE_BRAINPOOLP256R1 */ 26, CRYPT_ECCCURVE_BRAINPOOL_P256 },
683 { /* TLS_CURVE_BRAINPOOLP384R1 */ 27, CRYPT_ECCCURVE_BRAINPOOL_P384 },
684 { /* TLS_CURVE_BRAINPOOLP512R1 */ 28, CRYPT_ECCCURVE_BRAINPOOL_P512 },
685 { CRYPT_ERROR, 0 },
686 { CRYPT_ERROR, 0 }
687 };
688
689 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
getEccSslInfoTbl(OUT const MAP_TABLE ** sslInfoTblPtr,OUT_INT_Z int * noSslInfoTblEntries)690 static int getEccSslInfoTbl( OUT const MAP_TABLE **sslInfoTblPtr,
691 OUT_INT_Z int *noSslInfoTblEntries )
692 {
693 assert( isReadPtr( sslInfoTblPtr, sizeof( MAP_TABLE * ) ) );
694 assert( isWritePtr( noSslInfoTblEntries, sizeof( int ) ) );
695
696 *sslInfoTblPtr = sslCurveInfo;
697 *noSslInfoTblEntries = FAILSAFE_ARRAYSIZE( sslCurveInfo, MAP_TABLE );
698
699 return( CRYPT_OK );
700 }
701
702 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readSslEccPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)703 static int readSslEccPublicKey( INOUT STREAM *stream,
704 INOUT CONTEXT_INFO *contextInfoPtr,
705 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
706 {
707 PKC_INFO *eccKey = contextInfoPtr->ctxPKC;
708 const MAP_TABLE *sslCurveInfoPtr;
709 int value, curveID, sslCurveInfoNoEntries, status;
710
711 assert( isWritePtr( stream, sizeof( STREAM ) ) );
712 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
713 assert( isWritePtr( actionFlags, sizeof( int ) ) );
714
715 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
716 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDH );
717
718 /* Clear return value */
719 *actionFlags = ACTION_PERM_NONE;
720
721 /* Set the maximum permitted actions. SSL keys are only used
722 internally so we restrict the usage to internal-only. Since ECDH
723 keys can be both public and private keys we allow both usage
724 types even though technically it's a public key */
725 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
726 ACTION_PERM_NONE_EXTERNAL ) | \
727 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
728 ACTION_PERM_NONE_EXTERNAL );
729
730 /* Read the SSL public key information */
731 status = value = sgetc( stream );
732 if( cryptStatusError( status ) )
733 return( status );
734 if( value != 0x03 ) /* NamedCurve */
735 return( CRYPT_ERROR_BADDATA );
736 status = value = readUint16( stream );
737 if( cryptStatusError( status ) )
738 return( status );
739 if( value < 19 || value > 28 )
740 return( CRYPT_ERROR_NOTAVAIL );
741
742 /* Look up the curve ID based on the SSL NamedCurve ID */
743 status = getEccSslInfoTbl( &sslCurveInfoPtr, &sslCurveInfoNoEntries );
744 if( cryptStatusError( status ) )
745 return( status );
746 status = mapValue( value, &curveID, sslCurveInfoPtr,
747 sslCurveInfoNoEntries );
748 if( cryptStatusError( status ) )
749 return( status );
750 eccKey->curveType = curveID;
751
752 ENSURES( sanityCheckPKCInfo( eccKey ) );
753
754 return( CRYPT_OK );
755 }
756 #endif /* USE_ECDH */
757 #endif /* USE_SSL */
758
759 /****************************************************************************
760 * *
761 * Read PGP Public Keys *
762 * *
763 ****************************************************************************/
764
765 #ifdef USE_PGP
766
767 /* Read PGP public keys:
768
769 byte version
770 uint32 creationTime
771 [ uint16 validity - version 2 or 3 only ]
772 byte RSA DSA Elgamal ECDH/ECDSA
773 mpi n p p qx/qy
774 mpi e q g
775 mpi g y
776 mpi y */
777
778 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPgpHeader(INOUT STREAM * stream,OUT time_t * pgpCreationTime,const BOOLEAN openPgpOnly)779 static int readPgpHeader( INOUT STREAM *stream,
780 OUT time_t *pgpCreationTime,
781 const BOOLEAN openPgpOnly )
782 {
783 int version, value, status;
784
785 assert( isWritePtr( stream, sizeof( STREAM ) ) );
786 assert( isWritePtr( pgpCreationTime, sizeof( time_t ) ) );
787
788 /* Clear return value */
789 *pgpCreationTime = 0;
790
791 /* Read the PGP version info */
792 status = version = sgetc( stream );
793 if( cryptStatusError( status ) )
794 return( status );
795 if( openPgpOnly )
796 {
797 if( version != PGP_VERSION_OPENPGP )
798 return( CRYPT_ERROR_BADDATA );
799 }
800 else
801 {
802 if( version != PGP_VERSION_2 && version != PGP_VERSION_3 && \
803 version != PGP_VERSION_OPENPGP )
804 return( CRYPT_ERROR_BADDATA );
805 }
806
807 /* Read the creation time. In theory we should do this with
808 readUint32Time(), however some keys coming from non-PGP sources can
809 have a creation time of zero which would result in the value being
810 rejected by the time read. Because of this we have to read the value
811 as a standard 32-bit int and the perform the range check that's
812 otherwise performed by readUint32Time(), with an exception for a time
813 value of 0 */
814 status = value = readUint32( stream );
815 if( cryptStatusError( status ) )
816 return( status );
817 if( ( value < MIN_STORED_TIME_VALUE && value != 0 ) || \
818 value >= 0x7FFFFFFFL )
819 return( CRYPT_ERROR_BADDATA );
820 *pgpCreationTime = ( time_t ) value;
821
822 /* Skip the validity time if it's present */
823 if( version == PGP_VERSION_2 || version == PGP_VERSION_3 )
824 return( sSkip( stream, 2, 2 ) );
825
826 return( CRYPT_OK );
827 }
828
829 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readPgpRsaPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)830 static int readPgpRsaPublicKey( INOUT STREAM *stream,
831 INOUT CONTEXT_INFO *contextInfoPtr,
832 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
833 {
834 PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;
835 int value, status;
836
837 assert( isWritePtr( stream, sizeof( STREAM ) ) );
838 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
839 assert( isWritePtr( actionFlags, sizeof( int ) ) );
840
841 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
842 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
843
844 /* Clear return value */
845 *actionFlags = ACTION_PERM_NONE;
846
847 /* Read the header info */
848 status = readPgpHeader( stream, &rsaKey->pgpCreationTime, FALSE );
849 if( cryptStatusError( status ) )
850 return( status );
851
852 /* Set the maximum permitted actions. If there are no restrictions we
853 allow external usage, if the keys are encryption-only or signature-
854 only we make the usage internal-only because of RSA's signature/
855 encryption duality. If the key is a pure public key rather than
856 merely the public portions of a private key then the actions will be
857 restricted by higher-level code to encrypt/signature-check only */
858 status = value = sgetc( stream );
859 if( cryptStatusError( status ) )
860 return( status );
861 switch( value )
862 {
863 case PGP_ALGO_RSA:
864 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
865 ACTION_PERM_ALL ) | \
866 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
867 ACTION_PERM_ALL ) | \
868 MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
869 ACTION_PERM_ALL ) | \
870 MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
871 ACTION_PERM_ALL );
872 break;
873
874 case PGP_ALGO_RSA_ENCRYPT:
875 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
876 ACTION_PERM_NONE_EXTERNAL ) | \
877 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
878 ACTION_PERM_NONE_EXTERNAL );
879 break;
880
881 case PGP_ALGO_RSA_SIGN:
882 *actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
883 ACTION_PERM_NONE_EXTERNAL ) | \
884 MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
885 ACTION_PERM_NONE_EXTERNAL );
886 break;
887
888 default:
889 return( CRYPT_ERROR_BADDATA );
890 }
891
892 /* Read the PGP public key information */
893 status = readBignumInteger16UbitsChecked( stream, &rsaKey->rsaParam_n,
894 bytesToBits( RSAPARAM_MIN_N ),
895 bytesToBits( RSAPARAM_MAX_N ) );
896 if( cryptStatusOK( status ) )
897 status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_e,
898 bytesToBits( RSAPARAM_MIN_E ),
899 bytesToBits( RSAPARAM_MAX_E ),
900 &rsaKey->rsaParam_n );
901 if( cryptStatusError( status ) )
902 return( status );
903
904 ENSURES( sanityCheckPKCInfo( rsaKey ) );
905
906 return( CRYPT_OK );
907 }
908
909 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readPgpDlpPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)910 static int readPgpDlpPublicKey( INOUT STREAM *stream,
911 INOUT CONTEXT_INFO *contextInfoPtr,
912 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
913 {
914 PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;
915 int value, status;
916
917 assert( isWritePtr( stream, sizeof( STREAM ) ) );
918 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
919 assert( isWritePtr( actionFlags, sizeof( int ) ) );
920
921 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
922 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
923 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );
924
925 /* Clear return value */
926 *actionFlags = ACTION_PERM_NONE;
927
928 /* Read the header info */
929 status = readPgpHeader( stream, &dlpKey->pgpCreationTime, TRUE );
930 if( cryptStatusError( status ) )
931 return( status );
932
933 /* Set the maximum permitted actions. Because of the special-case data
934 formatting requirements for DLP algorithms we make the usage
935 internal-only. If the key is a pure public key rather than merely
936 the public portions of a private key then the actions will be
937 restricted by higher-level code to encrypt/signature-check only */
938 status = value = sgetc( stream );
939 if( cryptStatusError( status ) )
940 return( status );
941 switch( value )
942 {
943 case PGP_ALGO_DSA:
944 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
945 ACTION_PERM_NONE_EXTERNAL ) | \
946 MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
947 ACTION_PERM_NONE_EXTERNAL );
948 break;
949
950 case PGP_ALGO_ELGAMAL:
951 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
952 ACTION_PERM_NONE_EXTERNAL ) | \
953 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
954 ACTION_PERM_NONE_EXTERNAL );
955 break;
956
957 default:
958 return( CRYPT_ERROR_BADDATA );
959 }
960
961 /* Read the PGP public key information */
962 status = readBignumInteger16UbitsChecked( stream, &dlpKey->dlpParam_p,
963 bytesToBits( DLPPARAM_MIN_P ),
964 bytesToBits( DLPPARAM_MAX_P ) );
965 if( cryptStatusOK( status ) && value == PGP_ALGO_DSA )
966 status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_q,
967 bytesToBits( DLPPARAM_MIN_Q ),
968 bytesToBits( DLPPARAM_MAX_Q ),
969 &dlpKey->dlpParam_p );
970 if( cryptStatusOK( status ) )
971 status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_g,
972 bytesToBits( DLPPARAM_MIN_G ),
973 bytesToBits( DLPPARAM_MAX_G ),
974 &dlpKey->dlpParam_p );
975 if( cryptStatusOK( status ) )
976 status = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_y,
977 bytesToBits( DLPPARAM_MIN_Y ),
978 bytesToBits( DLPPARAM_MAX_Y ),
979 &dlpKey->dlpParam_p );
980 if( cryptStatusError( status ) )
981 return( status );
982
983 ENSURES( sanityCheckPKCInfo( dlpKey ) );
984
985 return( CRYPT_OK );
986 }
987
988 #if defined( USE_ECDH ) || defined( USE_ECDSA )
989
990 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readPgpEccPublicKey(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,OUT_FLAGS_Z (ACTION_PERM)int * actionFlags)991 static int readPgpEccPublicKey( INOUT STREAM *stream,
992 INOUT CONTEXT_INFO *contextInfoPtr,
993 OUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )
994 {
995 CRYPT_ECCCURVE_TYPE curveType;
996 PKC_INFO *eccKey = contextInfoPtr->ctxPKC;
997 STREAM oidStream;
998 BYTE oidBuffer[ 2 + MAX_OID_SIZE + 8 ];
999 int value, length, status;
1000
1001 assert( isWritePtr( stream, sizeof( STREAM ) ) );
1002 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1003 assert( isWritePtr( actionFlags, sizeof( int ) ) );
1004
1005 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
1006 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDSA || \
1007 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDH ) );
1008
1009 /* Clear return value */
1010 *actionFlags = ACTION_PERM_NONE;
1011
1012 /* Read the header info */
1013 status = readPgpHeader( stream, &eccKey->pgpCreationTime, TRUE );
1014 if( cryptStatusError( status ) )
1015 return( status );
1016
1017 /* Set the maximum permitted actions. Because of the special-case data
1018 formatting requirements for ECC algorithms (which are a part of the
1019 DLP algorithm family) we make the usage internal-only. If the key is
1020 a pure public key rather than merely the public portions of a private
1021 key then the actions will be restricted by higher-level code to
1022 encrypt/signature-check only */
1023 status = value = sgetc( stream );
1024 if( cryptStatusError( status ) )
1025 return( status );
1026 switch( value )
1027 {
1028 case PGP_ALGO_ECDH:
1029 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \
1030 ACTION_PERM_NONE_EXTERNAL ) | \
1031 MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \
1032 ACTION_PERM_NONE_EXTERNAL );
1033 break;
1034
1035 case PGP_ALGO_ECDSA:
1036 *actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGN, \
1037 ACTION_PERM_NONE_EXTERNAL ) | \
1038 MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \
1039 ACTION_PERM_NONE_EXTERNAL );
1040 break;
1041
1042 default:
1043 return( CRYPT_ERROR_BADDATA );
1044 }
1045
1046 /* Read the ECC OID, preceded by a length byte. For no known reason
1047 (probably a coding error that was made part of the spec), the PGP
1048 format omits the first two bytes of the OID, so we have to read the
1049 value into an intermediate buffer and recreate the full OID from
1050 it */
1051 status = length = sgetc( stream );
1052 if( cryptStatusError( status ) )
1053 return( status );
1054 if( length < MIN_OID_SIZE || length >= MAX_OID_SIZE )
1055 return( CRYPT_ERROR_BADDATA );
1056 oidBuffer[ 0 ] = 0x06; /* OID tag */
1057 oidBuffer[ 1 ] = intToByte( length );
1058 status = sread( stream, oidBuffer + 2, length );
1059 if( cryptStatusError( status ) )
1060 return( status );
1061 sMemConnect( &oidStream, oidBuffer, 2 + length );
1062 status = readECCOID( &oidStream, &curveType );
1063 sMemDisconnect( &oidStream );
1064 if( cryptStatusError( status ) )
1065 return( status );
1066 eccKey->curveType = curveType;
1067
1068 ENSURES( sanityCheckPKCInfo( eccKey ) );
1069
1070 /* We don't do PGP ECC yet since there's barely any use of it to test
1071 against */
1072 return( CRYPT_ERROR_BADDATA );
1073 }
1074 #endif /* USE_ECDH || USE_ECDSA */
1075 #endif /* USE_PGP */
1076
1077 /****************************************************************************
1078 * *
1079 * Public-Key Read Interface *
1080 * *
1081 ****************************************************************************/
1082
1083 /* Umbrella public-key read functions */
1084
1085 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
completePubkeyRead(INOUT CONTEXT_INFO * contextInfoPtr,IN_FLAGS (ACTION_PERM)const int actionFlags)1086 static int completePubkeyRead( INOUT CONTEXT_INFO *contextInfoPtr,
1087 IN_FLAGS( ACTION_PERM ) const int actionFlags )
1088 {
1089 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1090
1091 REQUIRES( actionFlags > ACTION_PERM_FLAG_NONE && \
1092 actionFlags < ACTION_PERM_FLAG_MAX );
1093
1094 /* If it's statically-initialised context data used in the self-test
1095 then there's no corresponding cryptlib object and we're done */
1096 if( contextInfoPtr->flags & CONTEXT_FLAG_STATICCONTEXT )
1097 return( CRYPT_OK );
1098
1099 /* Set the action permissions for the context */
1100 return( krnlSendMessage( contextInfoPtr->objectHandle,
1101 IMESSAGE_SETATTRIBUTE,
1102 ( MESSAGE_CAST ) &actionFlags,
1103 CRYPT_IATTRIBUTE_ACTIONPERMS ) );
1104 }
1105
1106 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPublicKeyRsaFunction(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,IN_ENUM (KEYFORMAT)const KEYFORMAT_TYPE formatType)1107 static int readPublicKeyRsaFunction( INOUT STREAM *stream,
1108 INOUT CONTEXT_INFO *contextInfoPtr,
1109 IN_ENUM( KEYFORMAT ) \
1110 const KEYFORMAT_TYPE formatType )
1111 {
1112 int actionFlags, status;
1113
1114 assert( isWritePtr( stream, sizeof( STREAM ) ) );
1115 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1116
1117 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
1118 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
1119 REQUIRES( formatType > KEYFORMAT_NONE && formatType < KEYFORMAT_LAST );
1120
1121 switch( formatType )
1122 {
1123 #ifdef USE_INT_ASN1
1124 case KEYFORMAT_CERT:
1125 status = readRsaSubjectPublicKey( stream, contextInfoPtr,
1126 &actionFlags );
1127 break;
1128 #endif /* USE_INT_ASN1 */
1129
1130 #ifdef USE_SSH
1131 case KEYFORMAT_SSH:
1132 status = readSshRsaPublicKey( stream, contextInfoPtr,
1133 &actionFlags );
1134 break;
1135 #endif /* USE_SSH */
1136
1137 #ifdef USE_PGP
1138 case KEYFORMAT_PGP:
1139 status = readPgpRsaPublicKey( stream, contextInfoPtr,
1140 &actionFlags );
1141 break;
1142 #endif /* USE_PGP */
1143
1144 default:
1145 retIntError();
1146 }
1147 if( cryptStatusError( status ) )
1148 return( status );
1149 return( completePubkeyRead( contextInfoPtr, actionFlags ) );
1150 }
1151
1152 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPublicKeyDlpFunction(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,IN_ENUM (KEYFORMAT)const KEYFORMAT_TYPE formatType)1153 static int readPublicKeyDlpFunction( INOUT STREAM *stream,
1154 INOUT CONTEXT_INFO *contextInfoPtr,
1155 IN_ENUM( KEYFORMAT ) \
1156 const KEYFORMAT_TYPE formatType )
1157 {
1158 int actionFlags, status;
1159
1160 assert( isWritePtr( stream, sizeof( STREAM ) ) );
1161 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1162
1163 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
1164 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DH || \
1165 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \
1166 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );
1167 REQUIRES( formatType > KEYFORMAT_NONE && formatType < KEYFORMAT_LAST );
1168
1169 switch( formatType )
1170 {
1171 #ifdef USE_INT_ASN1
1172 case KEYFORMAT_CERT:
1173 status = readDlpSubjectPublicKey( stream, contextInfoPtr,
1174 &actionFlags );
1175 break;
1176 #endif /* USE_INT_ASN1 */
1177
1178 #ifdef USE_SSH
1179 case KEYFORMAT_SSH:
1180 status = readSshDlpPublicKey( stream, contextInfoPtr,
1181 &actionFlags );
1182 break;
1183 #endif /* USE_SSH */
1184
1185 #ifdef USE_SSL
1186 case KEYFORMAT_SSL:
1187 status = readSslDlpPublicKey( stream, contextInfoPtr,
1188 &actionFlags );
1189 break;
1190 #endif /* USE_SSL */
1191
1192 #ifdef USE_PGP
1193 case KEYFORMAT_PGP:
1194 status = readPgpDlpPublicKey( stream, contextInfoPtr,
1195 &actionFlags );
1196 break;
1197 #endif /* USE_PGP */
1198
1199 default:
1200 retIntError();
1201 }
1202 if( cryptStatusError( status ) )
1203 return( status );
1204 return( completePubkeyRead( contextInfoPtr, actionFlags ) );
1205 }
1206
1207 #if defined( USE_ECDH ) || defined( USE_ECDSA )
1208
1209 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPublicKeyEccFunction(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,IN_ENUM (KEYFORMAT)const KEYFORMAT_TYPE formatType)1210 static int readPublicKeyEccFunction( INOUT STREAM *stream,
1211 INOUT CONTEXT_INFO *contextInfoPtr,
1212 IN_ENUM( KEYFORMAT ) \
1213 const KEYFORMAT_TYPE formatType )
1214 {
1215 int actionFlags, status;
1216
1217 assert( isWritePtr( stream, sizeof( STREAM ) ) );
1218 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1219
1220 REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
1221 ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDSA || \
1222 contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ECDH ) );
1223 REQUIRES( formatType == KEYFORMAT_CERT || formatType == KEYFORMAT_SSL || \
1224 formatType == KEYFORMAT_SSH || formatType == KEYFORMAT_PGP );
1225
1226 switch( formatType )
1227 {
1228 #ifdef USE_INT_ASN1
1229 case KEYFORMAT_CERT:
1230 status = readEccSubjectPublicKey( stream, contextInfoPtr,
1231 &actionFlags );
1232 break;
1233 #endif /* USE_INT_ASN1 */
1234
1235 /* TLS only uses ECDH (the ECDSA key data is conveyed in a
1236 certificate) so we only enable the TLS format if ECDH is defined
1237 rather than ECDH or ECDSA */
1238 #if defined( USE_SSL ) && defined( USE_ECDH )
1239 case KEYFORMAT_SSL:
1240 status = readSslEccPublicKey( stream, contextInfoPtr,
1241 &actionFlags );
1242 break;
1243 #endif /* USE_SSL && USE_ECDH */
1244
1245 #ifdef USE_SSH
1246 case KEYFORMAT_SSH:
1247 status = readSshEccPublicKey( stream, contextInfoPtr,
1248 &actionFlags );
1249 break;
1250 #endif /* USE_SSH */
1251
1252 #ifdef USE_PGP
1253 case KEYFORMAT_PGP:
1254 status = readPgpEccPublicKey( stream, contextInfoPtr,
1255 &actionFlags );
1256 break;
1257 #endif /* USE_SSH */
1258
1259 default:
1260 retIntError();
1261 }
1262 if( cryptStatusError( status ) )
1263 return( status );
1264 return( completePubkeyRead( contextInfoPtr, actionFlags ) );
1265 }
1266 #endif /* USE_ECDH || USE_ECDSA */
1267
1268 /****************************************************************************
1269 * *
1270 * Read DL Values *
1271 * *
1272 ****************************************************************************/
1273
1274 /* Unlike the simpler RSA PKC, DL-based PKCs produce a pair of values that
1275 need to be encoded as structured data. The following two functions
1276 decode the encoded forms from various formats. SSH assumes that DLP
1277 values are two fixed-size blocks of 20 bytes so we can't use the normal
1278 read/write routines to handle these values */
1279
1280 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \
IN_BUFFER(bufSize)1281 static int decodeDLValuesFunction( IN_BUFFER( bufSize ) const BYTE *buffer,
1282 IN_LENGTH_SHORT_MIN( 32 ) const int bufSize,
1283 INOUT BIGNUM *value1,
1284 INOUT BIGNUM *value2,
1285 const BIGNUM *maxRange,
1286 IN_ENUM( CRYPT_FORMAT ) \
1287 const CRYPT_FORMAT_TYPE formatType )
1288 {
1289 STREAM stream;
1290 int status;
1291
1292 assert( isReadPtr( buffer, bufSize ) );
1293 assert( isWritePtr( value1, sizeof( BIGNUM ) ) );
1294 assert( isWritePtr( value2, sizeof( BIGNUM ) ) );
1295 assert( isReadPtr( maxRange, sizeof( BIGNUM ) ) );
1296
1297 REQUIRES( bufSize >= 32 && bufSize < MAX_INTLENGTH_SHORT );
1298 REQUIRES( formatType > CRYPT_FORMAT_NONE && \
1299 formatType < CRYPT_FORMAT_LAST );
1300
1301 /* Clear return values */
1302 BN_clear( value1 );
1303 BN_clear( value2 );
1304
1305 sMemConnect( &stream, buffer, bufSize );
1306
1307 /* Read the DL components from the buffer and make sure that they're
1308 valid, i.e. that they're in the range [1...maxRange - 1] (the lower
1309 bound is actually DLPPARAM_MIN_SIG_x and not 1, which is > 100 bits).
1310 Although nominally intended for DLP algorithms the DLPPARAM_MIN_SIG_x
1311 values also work for ECC ones since they're also in the DLP family */
1312 switch( formatType )
1313 {
1314 #ifdef USE_INT_ASN1
1315 case CRYPT_FORMAT_CRYPTLIB:
1316 readSequence( &stream, NULL );
1317 status = readBignum( &stream, value1, DLPPARAM_MIN_SIG_R,
1318 CRYPT_MAX_PKCSIZE, maxRange );
1319 if( cryptStatusError( status ) )
1320 break;
1321 status = readBignum( &stream, value2, DLPPARAM_MIN_SIG_S,
1322 CRYPT_MAX_PKCSIZE, maxRange );
1323 break;
1324 #endif /* USE_INT_ASN1 */
1325
1326 #ifdef USE_PGP
1327 case CRYPT_FORMAT_PGP:
1328 status = readBignumInteger16Ubits( &stream, value1,
1329 DLPPARAM_MIN_SIG_R,
1330 bytesToBits( CRYPT_MAX_PKCSIZE ),
1331 maxRange );
1332 if( cryptStatusError( status ) )
1333 break;
1334 status = readBignumInteger16Ubits( &stream, value2,
1335 DLPPARAM_MIN_SIG_S,
1336 bytesToBits( CRYPT_MAX_PKCSIZE ),
1337 maxRange );
1338 break;
1339 #endif /* USE_PGP */
1340
1341 #ifdef USE_SSH
1342 case CRYPT_IFORMAT_SSH:
1343 status = importBignum( value1, buffer, 20, DLPPARAM_MIN_SIG_R,
1344 20, maxRange, KEYSIZE_CHECK_NONE );
1345 if( cryptStatusError( status ) )
1346 break;
1347 status = importBignum( value2, buffer + 20, 20, DLPPARAM_MIN_SIG_S,
1348 20, maxRange, KEYSIZE_CHECK_NONE );
1349 break;
1350 #endif /* USE_SSH */
1351
1352 default:
1353 retIntError();
1354 }
1355
1356 /* Clean up */
1357 sMemDisconnect( &stream );
1358 if( cryptStatusError( status ) )
1359 return( status );
1360
1361 ENSURES( sanityCheckBignum( value1 ) );
1362 ENSURES( sanityCheckBignum( value2 ) );
1363
1364 return( CRYPT_OK );
1365 }
1366
1367 #if defined( USE_ECDH ) || defined( USE_ECDSA )
1368
1369 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \
IN_BUFFER(bufSize)1370 static int decodeECDLValuesFunction( IN_BUFFER( bufSize ) const BYTE *buffer,
1371 IN_LENGTH_SHORT_MIN( 32 ) const int bufSize,
1372 INOUT BIGNUM *value1,
1373 INOUT BIGNUM *value2,
1374 const BIGNUM *maxRange,
1375 IN_ENUM( CRYPT_FORMAT ) \
1376 const CRYPT_FORMAT_TYPE formatType )
1377 {
1378 STREAM stream;
1379 int status;
1380
1381 assert( isReadPtr( buffer, bufSize ) );
1382 assert( isWritePtr( value1, sizeof( BIGNUM ) ) );
1383 assert( isWritePtr( value2, sizeof( BIGNUM ) ) );
1384 assert( isReadPtr( maxRange, sizeof( BIGNUM ) ) );
1385
1386 REQUIRES( bufSize >= 32 && bufSize < MAX_INTLENGTH_SHORT );
1387 REQUIRES( formatType > CRYPT_FORMAT_NONE && \
1388 formatType < CRYPT_FORMAT_LAST );
1389
1390 /* Clear return values */
1391 BN_clear( value1 );
1392 BN_clear( value2 );
1393
1394 /* In most cases the DLP and ECDLP formats are identical and we can just
1395 pass the call on to the DLP form, however SSH uses totally different
1396 signature formats depending on whether the signature is DSA or ECDSA,
1397 so we handle the SSH format explicitly here */
1398 if( formatType != CRYPT_IFORMAT_SSH )
1399 {
1400 return( decodeDLValuesFunction( buffer, bufSize, value1, value2,
1401 maxRange, formatType ) );
1402 }
1403 sMemConnect( &stream, buffer, bufSize );
1404 status = readBignumInteger32( &stream, value1, ECCPARAM_MIN_SIG_R,
1405 CRYPT_MAX_PKCSIZE_ECC, maxRange );
1406 if( cryptStatusOK( status ) )
1407 {
1408 status = readBignumInteger32( &stream, value2, ECCPARAM_MIN_SIG_S,
1409 CRYPT_MAX_PKCSIZE_ECC, maxRange );
1410 }
1411 sMemDisconnect( &stream );
1412 if( cryptStatusError( status ) )
1413 return( status );
1414
1415 ENSURES( sanityCheckBignum( value1 ) );
1416 ENSURES( sanityCheckBignum( value2 ) );
1417
1418 return( CRYPT_OK );
1419 }
1420 #endif /* USE_ECDH || USE_ECDSA */
1421
1422 /****************************************************************************
1423 * *
1424 * Context Access Routines *
1425 * *
1426 ****************************************************************************/
1427
1428 STDC_NONNULL_ARG( ( 1 ) ) \
initPubKeyRead(INOUT CONTEXT_INFO * contextInfoPtr)1429 void initPubKeyRead( INOUT CONTEXT_INFO *contextInfoPtr )
1430 {
1431 const CRYPT_ALGO_TYPE cryptAlgo = contextInfoPtr->capabilityInfo->cryptAlgo;
1432 PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
1433
1434 assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1435
1436 REQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );
1437
1438 /* Set the access method pointers */
1439 if( isDlpAlgo( cryptAlgo ) )
1440 {
1441 FNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyDlpFunction );
1442 FNPTR_SET( pkcInfo->decodeDLValuesFunction, decodeDLValuesFunction );
1443 return;
1444 }
1445 #if defined( USE_ECDH ) || defined( USE_ECDSA )
1446 if( isEccAlgo( cryptAlgo ) )
1447 {
1448 FNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyEccFunction );
1449 FNPTR_SET( pkcInfo->decodeDLValuesFunction, decodeECDLValuesFunction );
1450 return;
1451 }
1452 #endif /* USE_ECDH || USE_ECDSA */
1453 FNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyRsaFunction );
1454 }
1455 #else
1456
1457 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPublicKeyNullFunction(INOUT STREAM * stream,INOUT CONTEXT_INFO * contextInfoPtr,IN_ENUM (KEYFORMAT)const KEYFORMAT_TYPE formatType)1458 static int readPublicKeyNullFunction( INOUT STREAM *stream,
1459 INOUT CONTEXT_INFO *contextInfoPtr,
1460 IN_ENUM( KEYFORMAT ) \
1461 const KEYFORMAT_TYPE formatType )
1462 {
1463 return( CRYPT_ERROR_NOTAVAIL );
1464 }
1465
1466 STDC_NONNULL_ARG( ( 1 ) ) \
initPubKeyRead(INOUT CONTEXT_INFO * contextInfoPtr)1467 void initPubKeyRead( INOUT CONTEXT_INFO *contextInfoPtr )
1468 {
1469 FNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyNullFunction );
1470 }
1471 #endif /* USE_PKC */
1472