blob: c3236e188a08aae765a705b934b509b28d57ff4f [file] [log] [blame]
Nayna Jainc9deb182020-11-16 19:03:12 +00001/* Copyright 2019 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "common.h"
17
18#include "mbedtls/build_info.h"
19#if defined(MBEDTLS_PKCS7_C)
20#include "mbedtls/pkcs7.h"
21#include "mbedtls/x509.h"
22#include "mbedtls/asn1.h"
23#include "mbedtls/x509_crt.h"
24#include "mbedtls/x509_crl.h"
25#include "mbedtls/oid.h"
26
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#if defined(MBEDTLS_FS_IO)
31#include <sys/types.h>
32#include <sys/stat.h>
33#endif
34
35#if defined(MBEDTLS_PLATFORM_C)
36#include "mbedtls/platform.h"
37#include "mbedtls/platform_util.h"
38#else
39#include <stdio.h>
40#include <stdlib.h>
41#define mbedtls_free free
42#define mbedtls_calloc calloc
43#define mbedtls_printf printf
44#define mbedtls_snprintf snprintf
45#endif
46
47#if defined(MBEDTLS_HAVE_TIME)
48#include "mbedtls/platform_time.h"
49#endif
50#if defined(MBEDTLS_HAVE_TIME_DATE)
51#include <time.h>
52#endif
53
54/**
55 * Initializes the pkcs7 structure.
56 */
57void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
58{
59 memset( pkcs7, 0, sizeof( mbedtls_pkcs7 ) );
60 pkcs7->raw.p = NULL;
61}
62
63static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end,
64 size_t *len )
65{
66 int ret;
67
68 if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
69 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
70 {
71 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
72 }
73
74 return( 0 );
75}
76
77/**
78 * version Version
79 * Version ::= INTEGER
80 **/
81static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
82{
83 int ret;
84
85 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
86 return( MBEDTLS_ERR_PKCS7_INVALID_VERSION + ret );
87
88 /* If version != 1, return invalid version */
89 if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
90 return( MBEDTLS_ERR_PKCS7_INVALID_VERSION );
91
92 return( 0 );
93}
94
95/**
96 * ContentInfo ::= SEQUENCE {
97 * contentType ContentType,
98 * content
99 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
100 **/
101static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end,
102 mbedtls_pkcs7_buf *pkcs7 )
103{
104 size_t len = 0;
105 int ret;
106
107 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
108 | MBEDTLS_ASN1_SEQUENCE );
109 if( ret != 0 )
110 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
111
112 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
113 if( ret != 0 )
114 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
115
116 pkcs7->tag = MBEDTLS_ASN1_OID;
117 pkcs7->len = len;
118 pkcs7->p = *p;
119
120 return( ret );
121}
122
123/**
124 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
125 *
126 * This is from x509.h
127 **/
128static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end,
129 mbedtls_x509_buf *alg )
130{
131 int ret;
132
133 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
134 return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
135
136 return( 0 );
137}
138
139/**
140 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
141 **/
142static int pkcs7_get_digest_algorithm_set( unsigned char **p,
143 unsigned char *end,
144 mbedtls_x509_buf *alg )
145{
146 size_t len = 0;
147 int ret;
148
149 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
150 | MBEDTLS_ASN1_SET );
151 if( ret != 0 )
152 return( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
153
154 end = *p + len;
155
156 /** For now, it assumes there is only one digest algorithm specified **/
157 ret = mbedtls_asn1_get_alg_null( p, end, alg );
158 if( ret != 0 )
159 return( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
160
161 if ( *p != end )
162 return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT );
163
164 return( 0 );
165}
166
167/**
168 * certificates :: SET OF ExtendedCertificateOrCertificate,
169 * ExtendedCertificateOrCertificate ::= CHOICE {
170 * certificate Certificate -- x509,
171 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
172 * Return number of certificates added to the signed data,
173 * 0 or higher is valid.
174 * Return negative error code for failure.
175 **/
176static int pkcs7_get_certificates( unsigned char **p, unsigned char *end,
177 mbedtls_x509_crt *certs )
178{
179 int ret;
180 size_t len1 = 0;
181 size_t len2 = 0;
182 unsigned char *end_set, *end_cert;
183 unsigned char *start = *p;
184
185 if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
186 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
187 {
188 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
189 return( 0 );
190
191 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
192 }
193 start = *p;
194 end_set = *p + len1;
195
196 ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
197 | MBEDTLS_ASN1_SEQUENCE );
198 if( ret != 0 )
199 return( MBEDTLS_ERR_PKCS7_INVALID_CERT + ret );
200
201 end_cert = *p + len2;
202
203 /*
204 * This is to verify that there is only one signer certificate. It seems it is
205 * not easy to differentiate between the chain vs different signer's certificate.
206 * So, we support only the root certificate and the single signer.
207 * The behaviour would be improved with addition of multiple signer support.
208 */
209 if (end_cert != end_set)
210 return ( MBEDTLS_ERR_PKCS7_INVALID_CERT );
211
212 *p = start;
213 if( ( ret = mbedtls_x509_crt_parse( certs, *p, len1 ) ) < 0 )
214 return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
215
216 *p = *p + len1;
217
218 /* Since in this version we strictly support single certificate, and reaching
219 * here implies we have parsed successfully, we return 1. */
220
221 return( 1 );
222}
223
224/**
225 * EncryptedDigest ::= OCTET STRING
226 **/
227static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
228 mbedtls_pkcs7_buf *signature )
229{
230 int ret;
231 size_t len = 0;
232
233 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
234 if( ret != 0 )
235 return( ret );
236
237 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
238 signature->len = len;
239 signature->p = *p;
240
241 *p = *p + len;
242
243 return( 0 );
244}
245
246/**
247 * SignerInfos ::= SET of SignerInfo
248 * SignerInfo ::= SEQUENCE {
249 * version Version;
250 * issuerAndSerialNumber IssuerAndSerialNumber,
251 * digestAlgorithm DigestAlgorithmIdentifier,
252 * authenticatedAttributes
253 * [0] IMPLICIT Attributes OPTIONAL,
254 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
255 * encryptedDigest EncryptedDigest,
256 * unauthenticatedAttributes
257 * [1] IMPLICIT Attributes OPTIONAL,
258 * Return number of signers added to the signed data,
259 * 0 or higher is valid.
260 * Return negative error code for failure.
261 **/
262static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
263 mbedtls_pkcs7_signer_info *signers_set )
264{
265 unsigned char *end_set, *end_set_signer;
266 int ret;
267 size_t len = 0;
268
269 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
270 | MBEDTLS_ASN1_SET );
271 if( ret != 0 )
272 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
273
274 end_set = *p + len;
275
276 ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
277 | MBEDTLS_ASN1_SEQUENCE );
278 if( ret != 0 )
279 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
280
281 end_set_signer = *p + len;
282 if (end_set_signer != end_set)
283 return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
284
285 end_set = end_set_signer;
286
287 ret = mbedtls_asn1_get_int( p, end_set, &signers_set->version );
288 if( ret != 0 )
289 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
290
291 ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
292 | MBEDTLS_ASN1_SEQUENCE );
293 if( ret != 0 )
294 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
295
296 /* Parsing IssuerAndSerialNumber */
297 signers_set->issuer_raw.p = *p;
298
299 ret = mbedtls_asn1_get_tag( p, end_set, &len, MBEDTLS_ASN1_CONSTRUCTED
300 | MBEDTLS_ASN1_SEQUENCE );
301 if( ret != 0 )
302 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
303
304 ret = mbedtls_x509_get_name( p, *p + len, &signers_set->issuer );
305 if( ret != 0 )
306 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
307
308 signers_set->issuer_raw.len = *p - signers_set->issuer_raw.p;
309
310 ret = mbedtls_x509_get_serial( p, end_set, &signers_set->serial );
311 if( ret != 0 )
312 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
313
314 ret = pkcs7_get_digest_algorithm( p, end_set, &signers_set->alg_identifier );
315 if( ret != 0 )
316 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
317
318 ret = pkcs7_get_digest_algorithm( p, end_set, &signers_set->sig_alg_identifier );
319 if( ret != 0 )
320 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
321
322 ret = pkcs7_get_signature( p, end_set, &signers_set->sig );
323 if( ret != 0 )
324 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
325
326 signers_set->next = NULL;
327
328 if (*p != end_set)
329 return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
330
331 /* Since in this version we strictly support single signer, and reaching
332 * here implies we have parsed successfully, we return 1. */
333
334 return( 1 );
335}
336
337/**
338 * SignedData ::= SEQUENCE {
339 * version Version,
340 * digestAlgorithms DigestAlgorithmIdentifiers,
341 * contentInfo ContentInfo,
342 * certificates
343 * [0] IMPLICIT ExtendedCertificatesAndCertificates
344 * OPTIONAL,
345 * crls
346 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
347 * signerInfos SignerInfos }
348 */
349static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
350 mbedtls_pkcs7_signed_data *signed_data )
351{
352 unsigned char *p = buf;
353 unsigned char *end = buf + buflen;
354 unsigned char *end_set;
355 size_t len = 0;
356 int ret;
357 mbedtls_md_type_t md_alg;
358
359 ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
360 | MBEDTLS_ASN1_SEQUENCE );
361 if( ret != 0 )
362 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
363
364 end_set = p + len;
365
366 /* Get version of signed data */
367 ret = pkcs7_get_version( &p, end_set, &signed_data->version );
368 if( ret != 0 )
369 return( ret );
370
371 /* Get digest algorithm */
372 ret = pkcs7_get_digest_algorithm_set( &p, end_set,
373 &signed_data->digest_alg_identifiers );
374 if( ret != 0 )
375 return( ret );
376
377 ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
378 if( ret != 0 )
379 return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
380
381 /* Do not expect any content */
382 ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
383 if( ret != 0 )
384 return( ret );
385
386 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
387 {
388 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO ) ;
389 }
390
391 p = p + signed_data->content.oid.len;
392
393 /* Look for certificates, there may or may not be any */
394 mbedtls_x509_crt_init( &signed_data->certs );
395 ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
396 if( ret < 0 )
397 return( ret ) ;
398
399 signed_data->no_of_certs = ret;
400
401 /*
402 * Currently CRLs are not supported. If CRL exist, the parsing will fail
403 * at next step of getting signers info and return error as invalid
404 * signer info.
405 */
406
407 signed_data->no_of_crls = 0;
408
409 /* Get signers info */
410 ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
411 if( ret < 0 )
412 return( ret );
413
414 signed_data->no_of_signers = ret;
415
416 /* Support single signer */
417 if ( p != end )
418 ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
419
420 ret = 0;
421 return( ret );
422}
423
424int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
425 const size_t buflen )
426{
427 unsigned char *start;
428 unsigned char *end;
429 size_t len = 0;
430 int ret;
431
432 if( !pkcs7 )
433 return( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
434
435 /* make an internal copy of the buffer for parsing */
436 pkcs7->raw.p = start = mbedtls_calloc( 1, buflen );
437 if( pkcs7->raw.p == NULL )
438 {
439 return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
440 }
441 memcpy( start, buf, buflen );
442 pkcs7->raw.len = buflen;
443 end = start + buflen;
444
445 ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
446 if( ret != 0 )
447 goto out;
448
449 if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
450 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
451 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
452 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
453 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
454 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
455 {
456 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
457 goto out;
458 }
459
460 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
461 {
462 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
463 goto out;
464 }
465
466 start = start + pkcs7->content_type_oid.len;
467
468 ret = pkcs7_get_next_content_len( &start, end, &len );
469 if( ret != 0 )
470 goto out;
471
472 ret = pkcs7_get_signed_data( start, len, &pkcs7->signed_data );
473
474out:
475 if ( ret != 0 )
476 mbedtls_pkcs7_free( pkcs7 );
477 return( ret );
478}
479
480int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
481 const mbedtls_x509_crt *cert,
482 const unsigned char *data,
483 size_t datalen )
484{
485
486 int ret;
487 unsigned char *hash;
488 mbedtls_pk_context pk_cxt = cert->pk;
489 const mbedtls_md_info_t *md_info;
490 mbedtls_md_type_t md_alg;
491
492 ret = mbedtls_oid_get_md_alg( &pkcs7->signed_data.digest_alg_identifiers, &md_alg );
493 if( ret != 0 )
494 return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
495
496 md_info = mbedtls_md_info_from_type( md_alg );
497
498 hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
499 if( hash == NULL ) {
500 return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
501 }
502
503 mbedtls_md( md_info, data, datalen, hash );
504
505 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, 0,
506 pkcs7->signed_data.signers.sig.p,
507 pkcs7->signed_data.signers.sig.len );
508
509 mbedtls_free( hash );
510
511 return( ret );
512}
513
514int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
515 const mbedtls_x509_crt *cert,
516 const unsigned char *hash, size_t hashlen)
517{
518 int ret;
519 mbedtls_md_type_t md_alg;
520 mbedtls_pk_context pk_cxt;
521
522 ret = mbedtls_oid_get_md_alg( &pkcs7->signed_data.digest_alg_identifiers, &md_alg );
523 if( ret != 0 )
524 return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
525
526 pk_cxt = cert->pk;
527 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, hashlen,
528 pkcs7->signed_data.signers.sig.p,
529 pkcs7->signed_data.signers.sig.len );
530
531 return ( ret );
532}
533
534/*
535 * Unallocate all pkcs7 data
536 */
537void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
538{
539 mbedtls_x509_name *name_cur;
540 mbedtls_x509_name *name_prv;
541
542 if( pkcs7 == NULL || pkcs7->raw.p == NULL )
543 return;
544
545 mbedtls_free( pkcs7->raw.p );
546
547 mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
548 mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
549
550 name_cur = pkcs7->signed_data.signers.issuer.next;
551 while( name_cur != NULL )
552 {
553 name_prv = name_cur;
554 name_cur = name_cur->next;
555 mbedtls_free( name_prv );
556 }
557
558 pkcs7->raw.p = NULL;
559}
560
561#endif