pkcs7_format.c
Go to the documentation of this file.
1 /**
2  * @file pkcs7_format.c
3  * @brief PKCS #7 message formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "pkcs7/pkcs7_format.h"
37 #include "pkcs7/pkcs7_encrypt.h"
39 #include "pkix/x509_cert_format.h"
40 #include "pkix/x509_sign_format.h"
41 #include "encoding/asn1.h"
42 #include "encoding/oid.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (PKCS7_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Format contentInfo structure
51  * @param[in] contentInfo Pointer to the structure to format
52  * @param[out] output Buffer where to format the ASN.1 structure
53  * @param[out] written Length of the resulting ASN.1 structure
54  * @return Error code
55  **/
56 
58  uint8_t *output, size_t *written)
59 {
60  error_t error;
61  uint_t i;
62  size_t n;
63  size_t length;
64  uint8_t *p;
65  const uint8_t *content;
66  size_t contentLen;
67  Asn1Tag tag;
68 
69  //Point to the content
70  content = contentInfo->content.value;
71  contentLen = contentInfo->content.length;
72 
73  //Two-pass processing
74  for(i = 0; i < 2; i++)
75  {
76  //Point to the buffer where to write the ASN.1 structure
77  p = (i == 0) ? NULL : output;
78  //Length of the ASN.1 structure
79  length = 0;
80 
81  //Format contentType field
82  tag.constructed = FALSE;
85  tag.length = contentInfo->contentType.length;
86  tag.value = contentInfo->contentType.value;
87 
88  //Write the corresponding ASN.1 tag
89  error = asn1WriteTag(&tag, FALSE, p, &n);
90  //Any error to report?
91  if(error)
92  return error;
93 
94  //Advance data pointer
96  length += n;
97 
98  //The content field is optional, and if the field is not present, its
99  //intended value must be supplied by other means (refer to RFC 2315,
100  //section 7)
101  if(contentInfo->content.length > 0)
102  {
103  //Copy the content
104  if(p != NULL)
105  {
106  osMemmove(p, content, contentLen);
107  }
108 
109  //Its type is defined along with the object identifier for contentType
110  if(OID_COMP(contentInfo->contentType.value,
111  contentInfo->contentType.length, PKCS7_DATA_OID) == 0)
112  {
113  //The data content type is just an octet string (refer to RFC 2315,
114  //section 8)
115  tag.constructed = FALSE;
118  tag.length = contentLen;
119 
120  //Write the corresponding ASN.1 tag
121  error = asn1InsertHeader(&tag, p, &n);
122  //Any error to report?
123  if(error)
124  return error;
125  }
126  else
127  {
128  //The content field can contain any content type
129  n = 0;
130  }
131 
132  //Explicit tagging shall be used to encode the content field
133  tag.constructed = TRUE;
135  tag.objType = 0;
136  tag.length = contentLen + n;
137 
138  //Write the corresponding ASN.1 tag
139  error = asn1InsertHeader(&tag, p, &n);
140  //Any error to report?
141  if(error)
142  return error;
143 
144  //Advance data pointer
146  length += tag.totalLength;
147  }
148 
149  //The contentInfo structure is encapsulated within a sequence
150  tag.constructed = TRUE;
153  tag.length = length;
154 
155  //First pass?
156  if(i == 0)
157  {
158  //Write the corresponding ASN.1 tag
159  error = asn1InsertHeader(&tag, NULL, &n);
160  //Any error to report?
161  if(error)
162  return error;
163 
164  //The first pass calculates the length of the ASN.1 structure
165  n = tag.totalLength;
166 
167  //If the output parameter is NULL, then the function calculates the
168  //length of the ASN.1 structure without copying any data
169  if(output != NULL)
170  {
171  //Copy the message
172  osMemmove(output + n - contentLen, content, contentLen);
173  content = output + n - contentLen;
174  }
175  }
176  else
177  {
178  //Write the corresponding ASN.1 tag
179  error = asn1InsertHeader(&tag, output, &n);
180  //Any error to report?
181  if(error)
182  return error;
183 
184  //The second pass generates the ASN.1 structure
185  *written = tag.totalLength;
186  }
187  }
188 
189  //Successful processing
190  return NO_ERROR;
191 }
192 
193 
194 /**
195  * @brief Format signed-data content
196  * @param[in] prngAlgo PRNG algorithm
197  * @param[in] prngContext Pointer to the PRNG context
198  * @param[in] signedData Pointer to the structure to format
199  * @param[in] signerPrivateKey Pointer to the signer's private key
200  * @param[out] output Buffer where to format the ASN.1 structure
201  * @param[out] written Length of the resulting ASN.1 structure
202  * @return Error code
203  **/
204 
205 error_t pkcs7FormatSignedData(const PrngAlgo *prngAlgo, void *prngContext,
206  const Pkcs7SignedData *signedData, const void *signerPrivateKey,
207  uint8_t *output, size_t *written)
208 {
209  error_t error;
210  uint_t i;
211  size_t n;
212  size_t length;
213  uint8_t *p;
214  Asn1Tag tag;
215  Pkcs7ContentInfo contentInfo;
216 
217  //contentInfo is the content that is signed
218  contentInfo = signedData->contentInfo;
219 
220  //Two-pass processing
221  for(i = 0; i < 2; i++)
222  {
223  //Point to the buffer where to write the ASN.1 structure
224  p = (i == 0) ? NULL : output;
225  //Length of the ASN.1 structure
226  length = 0;
227 
228  //Format version field
229  error = asn1WriteInt32(signedData->version, FALSE, p, &n);
230  //Any error to report?
231  if(error)
232  return error;
233 
234  //Advance data pointer
235  ASN1_INC_POINTER(p, n);
236  length += n;
237 
238  //Format digestAlgorithms field
239  error = pkcs7FormatDigestAlgos(&signedData->digestAlgos, p, &n);
240  //Any error to report?
241  if(error)
242  return error;
243 
244  //Advance data pointer
245  ASN1_INC_POINTER(p, n);
246  length += n;
247 
248  //Format contentInfo field
249  error = pkcs7FormatContentInfo(&contentInfo, p, &n);
250  //Any error to report?
251  if(error)
252  return error;
253 
254  //Advance data pointer
255  ASN1_INC_POINTER(p, n);
256  length += n;
257 
258  //Format certificates field
259  error = pkcs7FormatCertificates(&signedData->certificates, p, &n);
260  //Any error to report?
261  if(error)
262  return error;
263 
264  //Advance data pointer
265  ASN1_INC_POINTER(p, n);
266  length += n;
267 
268  //Format crls field
269  error = pkcs7FormatCrls(&signedData->crls, p, &n);
270  //Any error to report?
271  if(error)
272  return error;
273 
274  //Advance data pointer
275  ASN1_INC_POINTER(p, n);
276  length += n;
277 
278  //Format signerInfos field
279  error = pkcs7FormatSignerInfos(prngAlgo, prngContext,
280  &signedData->signerInfos, signerPrivateKey, p, &n);
281  //Any error to report?
282  if(error)
283  return error;
284 
285  //Advance data pointer
286  ASN1_INC_POINTER(p, n);
287  length += n;
288 
289  //The SignedData structure is encapsulated within a sequence
290  tag.constructed = TRUE;
293  tag.length = length;
294 
295  //First pass?
296  if(i == 0)
297  {
298  //Write the corresponding ASN.1 tag
299  error = asn1InsertHeader(&tag, NULL, &n);
300  //Any error to report?
301  if(error)
302  return error;
303 
304  //The first pass calculates the length of the ASN.1 structure
305  n = tag.totalLength;
306 
307  //If the output parameter is NULL, then the function calculates the
308  //length of the ASN.1 structure without copying any data
309  if(output != NULL)
310  {
311  //Copy the message
312  osMemmove(output + n - contentInfo.content.length,
313  contentInfo.content.value, contentInfo.content.length);
314 
315  contentInfo.content.value = output + n - contentInfo.content.length;
316  }
317  }
318  else
319  {
320  //Write the corresponding ASN.1 tag
321  error = asn1InsertHeader(&tag, output, &n);
322  //Any error to report?
323  if(error)
324  return error;
325 
326  //The second pass generates the ASN.1 structure
327  *written = tag.totalLength;
328  }
329  }
330 
331  //Successful processing
332  return NO_ERROR;
333 }
334 
335 
336 /**
337  * @brief Format enveloped-data content
338  * @param[in] prngAlgo PRNG algorithm
339  * @param[in] prngContext Pointer to the PRNG context
340  * @param[in] recipientCertInfo Recipient's certificate
341  * @param[in] envelopedData Pointer to the structure to format
342  * @param[in] plaintext Pointer to the message to be encrypted
343  * @param[in] plaintextLen Length of the message, in bytes
344  * @param[out] output Buffer where to format the ASN.1 structure
345  * @param[out] written Length of the resulting ASN.1 structure
346  * @return Error code
347  **/
348 
349 error_t pkcs7FormatEnvelopedData(const PrngAlgo *prngAlgo, void *prngContext,
350  const X509CertInfo *recipientCertInfo, const Pkcs7EnvelopedData *envelopedData,
351  const uint8_t *plaintext, size_t plaintextLen, uint8_t *output, size_t *written)
352 {
353  error_t error;
354  uint_t i;
355  size_t n;
356  size_t length;
357  uint8_t *p;
358  uint8_t key[32];
359  size_t keyLen;
360  Asn1Tag tag;
361 
362  //Obtain the key length in octets
365  //Invalid key length?
366  if(keyLen == 0)
368 
369  //Generate a random encryption key
370  error = prngAlgo->read(prngContext, key, keyLen);
371  //Any error to report?
372  if(error)
373  return error;
374 
375  //Two-pass processing
376  for(i = 0; i < 2; i++)
377  {
378  //Point to the buffer where to write the ASN.1 structure
379  p = (i == 0) ? NULL : output;
380  //Length of the ASN.1 structure
381  length = 0;
382 
383  //Format version field
384  error = asn1WriteInt32(envelopedData->version, FALSE, p, &n);
385  //Any error to report?
386  if(error)
387  return error;
388 
389  //Advance data pointer
390  ASN1_INC_POINTER(p, n);
391  length += n;
392 
393  //Format recipientInfos field
394  error = pkcs7FormatRecipientInfos(prngAlgo, prngContext,
395  &envelopedData->recipientInfos, recipientCertInfo, key, keyLen, p, &n);
396  //Any error to report?
397  if(error)
398  return error;
399 
400  //Advance data pointer
401  ASN1_INC_POINTER(p, n);
402  length += n;
403 
404  //Format encryptedContentInfo field
406  key, keyLen, plaintext, plaintextLen, p, &n);
407  //Any error to report?
408  if(error)
409  return error;
410 
411  //Advance data pointer
412  ASN1_INC_POINTER(p, n);
413  length += n;
414 
415  //The EnvelopedData structure is encapsulated within a sequence
416  tag.constructed = TRUE;
419  tag.length = length;
420 
421  //First pass?
422  if(i == 0)
423  {
424  //Write the corresponding ASN.1 tag
425  error = asn1InsertHeader(&tag, NULL, &n);
426  //Any error to report?
427  if(error)
428  return error;
429 
430  //The first pass calculates the length of the ASN.1 structure
431  n = tag.totalLength;
432 
433  //Copy the message to be encrypted
434  if(output != NULL)
435  {
436  osMemmove(output + n - plaintextLen, plaintext, plaintextLen);
437  plaintext = output + n - plaintextLen;
438  }
439  }
440  else
441  {
442  //Write the corresponding ASN.1 tag
443  error = asn1InsertHeader(&tag, output, &n);
444  //Any error to report?
445  if(error)
446  return error;
447 
448  //The second pass generates the ASN.1 structure
449  *written = tag.totalLength;
450  }
451  }
452 
453  //Successful processing
454  return NO_ERROR;
455 }
456 
457 
458 /**
459  * @brief Format digestAlgos structure
460  * @param[in] digestAlgos Pointer to the structure to format
461  * @param[out] output Buffer where to format the ASN.1 structure
462  * @param[out] written Length of the resulting ASN.1 structure
463  * @return Error code
464  **/
465 
467  uint8_t *output, size_t *written)
468 {
469  error_t error;
470  uint_t i;
471  size_t n;
472  size_t length;
473  uint8_t *p;
474  Asn1Tag tag;
475 
476  //Point to the buffer where to write the ASN.1 structure
477  p = output;
478  //Length of the ASN.1 structure
479  length = 0;
480 
481  //digestAlgorithms is a collection of message-digest algorithm identifiers.
482  //There may be any number of elements in the collection, including zero
483  //(refer to RFC 2315, section 9.1)
484  for(i = 0; i < digestAlgos->numIdentifiers; i++)
485  {
486  //Format DigestAlgorithmIdentifier structure
487  error = pkcs7FormatAlgoId(&digestAlgos->identifiers[i], p, &n);
488  //Any error to report?
489  if(error)
490  return error;
491 
492  //Advance data pointer
493  ASN1_INC_POINTER(p, n);
494  length += n;
495  }
496 
497  //The digestAlgorithms structure is encapsulated within a set
498  tag.constructed = TRUE;
500  tag.objType = ASN1_TYPE_SET;
501  tag.length = n;
502 
503  //Write the corresponding ASN.1 tag
504  error = asn1InsertHeader(&tag, output, &n);
505  //Any error to report?
506  if(error)
507  return error;
508 
509  //Total length of the ASN.1 structure
510  *written = tag.totalLength;
511 
512  //Successful processing
513  return NO_ERROR;
514 }
515 
516 
517 /**
518  * @brief Format certificates
519  * @param[in] certificates Pointer to the structure to format
520  * @param[out] output Buffer where to format the ASN.1 structure
521  * @param[out] written Length of the resulting ASN.1 structure
522  * @return Error code
523  **/
524 
526  uint8_t *output, size_t *written)
527 {
528  error_t error;
529  uint_t i;
530  size_t n;
531  size_t length;
532  uint8_t *p;
533  Asn1Tag tag;
534 
535  //Point to the buffer where to write the ASN.1 structure
536  p = output;
537  //Length of the ASN.1 structure
538  length = 0;
539 
540  //Raw ASN.1 sequence?
541  if(certificates->raw.value != NULL && certificates->raw.length > 0)
542  {
543  //Copy raw ASN.1 sequence
544  if(output != NULL)
545  {
546  osMemcpy(p, certificates->raw.value, certificates->raw.length);
547  }
548 
549  //Advance data pointer
550  ASN1_INC_POINTER(p, certificates->raw.length);
551  length += certificates->raw.length;
552  }
553  else
554  {
555  //The ExtendedCertificatesAndCertificates type gives a set of extended
556  //certificates and X.509 certificates (refer to RFC 2315, section 6.6)
557  for(i = 0; i < certificates->numCertificates; i++)
558  {
559  //The ExtendedCertificateOrCertificate type gives either a PKCS #6
560  //extended certificate or an X.509 certificate
561  if(output != NULL)
562  {
563  osMemcpy(p, certificates->certificates[i].value,
564  certificates->certificates[i].length);
565  }
566 
567  //Advance data pointer
568  ASN1_INC_POINTER(p, certificates->certificates[i].length);
569  length += certificates->certificates[i].length;
570  }
571  }
572 
573  //The certificates field is optional
574  if(length > 0)
575  {
576  //Implicit tagging is used to encode the crls field
577  tag.constructed = TRUE;
579  tag.objType = 0;
580  tag.length = length;
581 
582  //Write the corresponding ASN.1 tag
583  error = asn1InsertHeader(&tag, output, &n);
584  //Any error to report?
585  if(error)
586  return error;
587 
588  //Total length of the ASN.1 structure
589  *written = tag.totalLength;
590  }
591  else
592  {
593  //The certificates field is not present
594  *written = 0;
595  }
596 
597  //Successful processing
598  return NO_ERROR;
599 }
600 
601 
602 /**
603  * @brief Format CRLs
604  * @param[in] crls Pointer to the structure to format
605  * @param[out] output Buffer where to format the ASN.1 structure
606  * @param[out] written Length of the resulting ASN.1 structure
607  * @return Error code
608  **/
609 
610 error_t pkcs7FormatCrls(const Pkcs7Crls *crls, uint8_t *output,
611  size_t *written)
612 {
613  error_t error;
614  uint_t i;
615  size_t n;
616  size_t length;
617  uint8_t *p;
618  Asn1Tag tag;
619 
620  //Point to the buffer where to write the ASN.1 structure
621  p = output;
622  //Length of the ASN.1 structure
623  length = 0;
624 
625  //Raw ASN.1 sequence?
626  if(crls->raw.value != NULL && crls->raw.length > 0)
627  {
628  //Copy raw ASN.1 sequence
629  if(output != NULL)
630  {
631  osMemcpy(p, crls->raw.value, crls->raw.length);
632  }
633 
634  //Advance data pointer
635  ASN1_INC_POINTER(p, crls->raw.length);
636  length += crls->raw.length;
637  }
638  else
639  {
640  //The CertificateRevocationLists type gives a set of certificate-
641  //revocation lists (refer to RFC 2315, section 6.1)
642  for(i = 0; i < crls->numCrls; i++)
643  {
644  //The CertificateRevocationList type contains information about
645  //certificates whose validity an issuer has prematurely revoked
646  if(output != NULL)
647  {
648  osMemcpy(p, crls->crls[i].value, crls->crls[i].length);
649  }
650 
651  //Advance data pointer
652  ASN1_INC_POINTER(p, crls->crls[i].length);
653  length += crls->crls[i].length;
654  }
655  }
656 
657  //The crls field is optional
658  if(length > 0)
659  {
660  //Implicit tagging is used to encode the crls field
661  tag.constructed = TRUE;
663  tag.objType = 1;
664  tag.length = length;
665 
666  //Write the corresponding ASN.1 tag
667  error = asn1InsertHeader(&tag, output, &n);
668  //Any error to report?
669  if(error)
670  return error;
671 
672  //Total length of the ASN.1 structure
673  *written = tag.totalLength;
674  }
675  else
676  {
677  //The crls field is not present
678  *written = 0;
679  }
680 
681  //Successful processing
682  return NO_ERROR;
683 }
684 
685 
686 /**
687  * @brief Format SignerInfos structure
688  * @param[in] prngAlgo PRNG algorithm
689  * @param[in] prngContext Pointer to the PRNG context
690  * @param[in] signerInfos Pointer to the structure to format
691  * @param[in] signerPrivateKey Pointer to the signer's private key
692  * @param[out] output Buffer where to format the ASN.1 structure
693  * @param[out] written Length of the resulting ASN.1 structure
694  * @return Error code
695  **/
696 
697 error_t pkcs7FormatSignerInfos(const PrngAlgo *prngAlgo, void *prngContext,
698  const Pkcs7SignerInfos *signerInfos, const void *signerPrivateKey,
699  uint8_t *output, size_t *written)
700 {
701  error_t error;
702  uint_t i;
703  size_t n;
704  size_t length;
705  uint8_t *p;
706  Asn1Tag tag;
707 
708  //Point to the buffer where to write the ASN.1 structure
709  p = output;
710  //Length of the ASN.1 structure
711  length = 0;
712 
713  //signerInfos is a collection of per-signer information. There may be any
714  //number of elements in the collection, including zero (refer to RFC 2315,
715  //section 9.1)
716  for(i = 0; i < signerInfos->numSignerInfos; i++)
717  {
718  //Format SignerInfo structure
719  error = pkcs7FormatSignerInfo(prngAlgo, prngContext,
720  &signerInfos->signerInfos[i], signerPrivateKey, p, &n);
721  //Any error to report?
722  if(error)
723  return error;
724 
725  //Advance data pointer
726  ASN1_INC_POINTER(p, n);
727  length += n;
728  }
729 
730  //The signerInfos structure is encapsulated within a set
731  tag.constructed = TRUE;
733  tag.objType = ASN1_TYPE_SET;
734  tag.length = n;
735 
736  //Write the corresponding ASN.1 tag
737  error = asn1InsertHeader(&tag, output, &n);
738  //Any error to report?
739  if(error)
740  return error;
741 
742  //Total length of the ASN.1 structure
743  *written = tag.totalLength;
744 
745  //Successful processing
746  return NO_ERROR;
747 }
748 
749 
750 /**
751  * @brief Format SignerInfo structure
752  * @param[in] prngAlgo PRNG algorithm
753  * @param[in] prngContext Pointer to the PRNG context
754  * @param[in] signerInfo Pointer to the structure to format
755  * @param[in] signerPrivateKey Pointer to the signer's private key
756  * @param[out] output Buffer where to format the ASN.1 structure
757  * @param[out] written Length of the resulting ASN.1 structure
758  * @return Error code
759  **/
760 
761 error_t pkcs7FormatSignerInfo(const PrngAlgo *prngAlgo, void *prngContext,
762  const Pkcs7SignerInfo *signerInfo, const void *signerPrivateKey,
763  uint8_t *output, size_t *written)
764 {
765  error_t error;
766  size_t n;
767  size_t length;
768  uint8_t *p;
769  uint8_t digest[MAX_HASH_DIGEST_SIZE];
770  Asn1Tag tag;
771 
772  //Point to the buffer where to write the ASN.1 structure
773  p = output;
774  //Length of the ASN.1 structure
775  length = 0;
776 
777  //Format version field
778  error = asn1WriteInt32(signerInfo->version, FALSE, p, &n);
779  //Any error to report?
780  if(error)
781  return error;
782 
783  //Advance data pointer
784  ASN1_INC_POINTER(p, n);
785  length += n;
786 
787  //Format issuerAndSerialNumber field
789  p, &n);
790  //Any error to report?
791  if(error)
792  return error;
793 
794  //Advance data pointer
795  ASN1_INC_POINTER(p, n);
796  length += n;
797 
798  //Format digestAlgorithm field
799  error = pkcs7FormatAlgoId(&signerInfo->digestAlgo, p, &n);
800  //Any error to report?
801  if(error)
802  return error;
803 
804  //Advance data pointer
805  ASN1_INC_POINTER(p, n);
806  length += n;
807 
808  //Format authenticatedAttributes field
810  p, &n);
811  //Any error to report?
812  if(error)
813  return error;
814 
815  //If the output parameter is NULL, then the function calculates the length
816  //of the ASN.1 structure without copying any data
817  if(p != NULL)
818  {
819  //The IMPLICIT [0] tag in the authenticatedAttributes field is not part
820  //of the Attributes value (refer to RFC 2315, section 9.3)
821  error = asn1ReadTag(p, n, &tag);
822  //Any error to report?
823  if(error)
824  return error;
825 
826  //Digest the DER encoding of the authenticatedAttributes field
827  error = pkcs7DigestAuthenticatedAttributes(signerInfo, tag.value,
828  tag.length, digest);
829  //Any error to report?
830  if(error)
831  return error;
832  }
833 
834  //Advance data pointer
835  ASN1_INC_POINTER(p, n);
836  length += n;
837 
838  //Format digestEncryptionAlgorithm field
840  p, &n);
841  //Any error to report?
842  if(error)
843  return error;
844 
845  //Advance data pointer
846  ASN1_INC_POINTER(p, n);
847  length += n;
848 
849  //Format encryptedDigest field
850  error = pkcs7FormatEncryptedDigest(prngAlgo, prngContext, digest,
851  signerInfo, signerPrivateKey, p, &n);
852  //Any error to report?
853  if(error)
854  return error;
855 
856  //Advance data pointer
857  ASN1_INC_POINTER(p, n);
858  length += n;
859 
860  //Format unauthenticatedAttributes field
862  p, &n);
863  //Any error to report?
864  if(error)
865  return error;
866 
867  //Advance data pointer
868  ASN1_INC_POINTER(p, n);
869  length += n;
870 
871  //The SignerInfo structure is encapsulated within a sequence
872  tag.constructed = TRUE;
875  tag.length = length;
876 
877  //Write the corresponding ASN.1 tag
878  error = asn1InsertHeader(&tag, output, &n);
879  //Any error to report?
880  if(error)
881  return error;
882 
883  //Total number of bytes that have been written
884  *written = tag.totalLength;
885 
886  //Successful processing
887  return NO_ERROR;
888 }
889 
890 
891 /**
892  * @brief Format IssuerAndSerialNumber structure
893  * @param[in] issuerAndSerialNumber Pointer to the structure to format
894  * @param[out] output Buffer where to format the ASN.1 structure
895  * @param[out] written Length of the resulting ASN.1 structure
896  * @return Error code
897  **/
898 
900  uint8_t *output, size_t *written)
901 {
902  error_t error;
903  size_t n;
904  size_t length;
905  uint8_t *p;
906  Asn1Tag tag;
907 
908  //Point to the buffer where to write the ASN.1 structure
909  p = output;
910  //Length of the ASN.1 structure
911  length = 0;
912 
913  //Format issuer field
914  error = x509FormatName(&issuerAndSerialNumber->name, p, &n);
915  //Any error to report?
916  if(error)
917  return error;
918 
919  //Advance data pointer
920  ASN1_INC_POINTER(p, n);
921  length += n;
922 
923  //Format serialNumber field
924  error = x509FormatSerialNumber(NULL, NULL,
925  &issuerAndSerialNumber->serialNumber, p, &n);
926  //Any error to report?
927  if(error)
928  return error;
929 
930  //Advance data pointer
931  ASN1_INC_POINTER(p, n);
932  length += n;
933 
934  //The IssuerAndSerialNumber structure is encapsulated within a sequence
935  tag.constructed = TRUE;
938  tag.length = length;
939 
940  //Write the corresponding ASN.1 tag
941  error = asn1InsertHeader(&tag, output, &n);
942  //Any error to report?
943  if(error)
944  return error;
945 
946  //Total number of bytes that have been written
947  *written = tag.totalLength;
948 
949  //Successful processing
950  return NO_ERROR;
951 }
952 
953 
954 /**
955  * @brief Format authenticatedAttributes structure
956  * @param[in] authenticatedAttributes Pointer to the structure to format
957  * @param[out] output Buffer where to format the ASN.1 structure
958  * @param[out] written Length of the resulting ASN.1 structure
959  * @return Error code
960  **/
961 
963  uint8_t *output, size_t *written)
964 {
965  error_t error;
966  uint_t i;
967  size_t n;
968  size_t length;
969  Asn1Tag tag;
970  Pkcs7Attribute attribute;
971 
972  //Length of the ASN.1 structure
973  length = 0;
974 
975  //Format PKCS #9 Content Type attribute
976  if(authenticatedAttributes->contentType.length > 0)
977  {
978  //Set attribute type and value
979  attribute.oid.value = PKCS9_CONTENT_TYPE_OID;
980  attribute.oid.length = sizeof(PKCS9_CONTENT_TYPE_OID);
981  attribute.type = ASN1_TYPE_OBJECT_IDENTIFIER;
982  attribute.data.value = authenticatedAttributes->contentType.value;
983  attribute.data.length = authenticatedAttributes->contentType.length;
984 
985  //Encode the attribute to ASN.1 format
986  error = pkcs7AddAttribute(&attribute, output, &length);
987  //Any error to report?
988  if(error)
989  return error;
990  }
991 
992  //Format PKCS #9 Message Digest attribute
993  if(authenticatedAttributes->messageDigest.length > 0)
994  {
995  //Set attribute type and value
996  attribute.oid.value = PKCS9_MESSAGE_DIGEST_OID;
997  attribute.oid.length = sizeof(PKCS9_MESSAGE_DIGEST_OID);
998  attribute.type = ASN1_TYPE_OCTET_STRING;
999  attribute.data.value = authenticatedAttributes->messageDigest.value;
1000  attribute.data.length = authenticatedAttributes->messageDigest.length;
1001 
1002  //Encode the attribute to ASN.1 format
1003  error = pkcs7AddAttribute(&attribute, output, &length);
1004  //Any error to report?
1005  if(error)
1006  return error;
1007  }
1008 
1009  //Format PKCS #9 Signing Time attribute
1010  if(authenticatedAttributes->signingTime.year > 0)
1011  {
1012  char_t buffer[24];
1013 
1014  //UTCTime is limited to the period from 1950 to 2049
1015  if(authenticatedAttributes->signingTime.year >= 1950 &&
1016  authenticatedAttributes->signingTime.year <= 2049)
1017  {
1018  //Use UTCTime format
1019  attribute.type = ASN1_TYPE_UTC_TIME;
1020  }
1021  else
1022  {
1023  //Use GeneralizedTime format
1024  attribute.type = ASN1_TYPE_GENERALIZED_TIME;
1025  }
1026 
1027  //Format UTCTime or GeneralizedTime string
1028  error = x509FormatTimeString(&authenticatedAttributes->signingTime,
1029  attribute.type, buffer);
1030  //Any error to report?
1031  if(error)
1032  return error;
1033 
1034  //Set attribute type and value
1035  attribute.oid.value = PKCS9_SIGNING_TIME_OID;
1036  attribute.oid.length = sizeof(PKCS9_SIGNING_TIME_OID);
1037  attribute.data.value = (uint8_t *) buffer;
1038  attribute.data.length = osStrlen(buffer);
1039 
1040  //Encode the attribute to ASN.1 format
1041  error = pkcs7AddAttribute(&attribute, output, &length);
1042  //Any error to report?
1043  if(error)
1044  return error;
1045  }
1046 
1047  //Add custom attributes, if any
1048  for(i = 0; i < authenticatedAttributes->numCustomAttributes; i++)
1049  {
1050  //Encode the attribute to ASN.1 format
1051  error = pkcs7AddAttribute(&authenticatedAttributes->customAttributes[i],
1052  output, &length);
1053  //Any error to report?
1054  if(error)
1055  return error;
1056  }
1057 
1058  //Any attributes written?
1059  if(length > 0)
1060  {
1061  //Implicit tagging shall be used to encode the authenticatedAttributes
1062  //structure
1063  tag.constructed = TRUE;
1065  tag.objType = 0;
1066  tag.length = length;
1067 
1068  //Write the corresponding ASN.1 tag
1069  error = asn1InsertHeader(&tag, output, &n);
1070  //Any error to report?
1071  if(error)
1072  return error;
1073 
1074  //Total length of the ASN.1 structure
1075  *written = tag.totalLength;
1076  }
1077  else
1078  {
1079  //The authenticatedAttributes field is optional
1080  *written = 0;
1081  }
1082 
1083  //Successful processing
1084  return NO_ERROR;
1085 }
1086 
1087 
1088 /**
1089  * @brief Format digestEncryptionAlgorithm structure
1090  * @param[in] digestEncryptionAlgo Pointer to the structure to format
1091  * @param[out] output Buffer where to format the ASN.1 structure
1092  * @param[out] written Length of the resulting ASN.1 structure
1093  * @return Error code
1094  **/
1095 
1097  uint8_t *output, size_t *written)
1098 {
1099  error_t error;
1100  size_t n;
1101  size_t length;
1102  uint8_t *p;
1103  size_t oidLen;
1104  const uint8_t *oid;
1105  Asn1Tag tag;
1106 
1107  //Get the signature algorithm identifier
1108  oid = digestEncryptionAlgo->oid.value;
1109  oidLen = digestEncryptionAlgo->oid.length;
1110 
1111  //Point to the buffer where to write the ASN.1 structure
1112  p = output;
1113  //Length of the ASN.1 structure
1114  length = 0;
1115 
1116  //digestEncryptionAlgorithm identifies the digest-encryption algorithm under
1117  //which the message digest and associated information are encrypted with the
1118  //signer's private key (refer to RFC 2315, section 9.2)
1119  tag.constructed = FALSE;
1122  tag.length = digestEncryptionAlgo->oid.length;
1123  tag.value = digestEncryptionAlgo->oid.value;
1124 
1125  //Write the corresponding ASN.1 tag
1126  error = asn1WriteTag(&tag, FALSE, p, &n);
1127  //Any error to report?
1128  if(error)
1129  return error;
1130 
1131  //Advance data pointer
1132  ASN1_INC_POINTER(p, n);
1133  length += n;
1134 
1135 #if (PKCS7_RSA_SUPPORT == ENABLED && RSA_SUPPORT == ENABLED)
1136  //RSA signature algorithm?
1137  if(OID_COMP(oid, oidLen, RSA_ENCRYPTION_OID) == 0 ||
1144  {
1145  //For RSA signature algorithm, the parameters component of that type
1146  //shall be the ASN.1 type NULL (refer to RFC 3279, section 2.2.1)
1147  tag.constructed = FALSE;
1149  tag.objType = ASN1_TYPE_NULL;
1150  tag.length = 0;
1151  tag.value = NULL;
1152 
1153  //Write the corresponding ASN.1 tag
1154  error = asn1WriteTag(&tag, FALSE, p, &n);
1155  }
1156  else
1157 #endif
1158 #if (PKCS7_RSA_PSS_SUPPORT == ENABLED && RSA_SUPPORT == ENABLED)
1159  //RSA-PSS signature algorithm?
1160  if(OID_COMP(oid, oidLen, RSASSA_PSS_OID) == 0)
1161  {
1162  //The parameters must be present when used in the algorithm identifier
1163  //associated with a signature value (refer to RFC 4055, section 3.1)
1164  error = x509FormatRsaPssParameters(&digestEncryptionAlgo->rsaPssParams,
1165  p, &n);
1166  }
1167  else
1168 #endif
1169  //Invalid signature algorithm?
1170  {
1171  //Report an error
1173  }
1174 
1175  //Check status code
1176  if(error)
1177  return error;
1178 
1179  //Advance data pointer
1180  ASN1_INC_POINTER(p, n);
1181  length += n;
1182 
1183  //The Algorithm and Parameters fields are encapsulated within a sequence
1184  tag.constructed = TRUE;
1187  tag.length = length;
1188 
1189  //Write the corresponding ASN.1 tag
1190  error = asn1InsertHeader(&tag, output, &n);
1191  //Any error to report?
1192  if(error)
1193  return error;
1194 
1195  //Total number of bytes that have been written
1196  *written = length + n;
1197 
1198  //Successful processing
1199  return NO_ERROR;
1200 }
1201 
1202 
1203 /**
1204  * @brief Format encryptedDigest structure
1205  * @param[in] prngAlgo PRNG algorithm
1206  * @param[in] prngContext Pointer to the PRNG context
1207  * @param[in] digest Message digest
1208  * @param[in] signerInfo Pointer to the signer information
1209  * @param[in] signerPrivateKey Pointer to the signer's private key
1210  * @param[out] output Buffer where to format the ASN.1 structure
1211  * @param[out] written Length of the resulting ASN.1 structure
1212  * @return Error code
1213  **/
1214 
1215 error_t pkcs7FormatEncryptedDigest(const PrngAlgo *prngAlgo, void *prngContext,
1216  const uint8_t *digest, const Pkcs7SignerInfo *signerInfo,
1217  const void *signerPrivateKey, uint8_t *output, size_t *written)
1218 {
1219  error_t error;
1220  size_t n;
1221  Asn1Tag tag;
1222 
1223  //encryptedDigest is the result of digital signature generation, using the
1224  //message digest and the signer's private key
1225  error = pkcs7GenerateSignature(prngAlgo, prngContext, digest, signerInfo,
1226  signerPrivateKey, output, &n);
1227  //Any error to report?
1228  if(error)
1229  return error;
1230 
1231  //The signature value generated by the signer must be encoded as an octet
1232  //string
1233  tag.constructed = FALSE;
1236  tag.length = n;
1237 
1238  //Write the corresponding ASN.1 tag
1239  error = asn1InsertHeader(&tag, output, &n);
1240  //Any error to report?
1241  if(error)
1242  return error;
1243 
1244  //Total number of bytes that have been written
1245  *written = tag.totalLength;
1246 
1247  //Successful processing
1248  return NO_ERROR;
1249 }
1250 
1251 
1252 /**
1253  * @brief Format unauthenticatedAttributes structure
1254  * @param[in] unauthenticatedAttributes Pointer to the structure to format
1255  * @param[out] output Buffer where to format the ASN.1 structure
1256  * @param[out] written Length of the resulting ASN.1 structure
1257  * @return Error code
1258  **/
1259 
1261  uint8_t *output, size_t *written)
1262 {
1263  error_t error;
1264  uint_t i;
1265  size_t n;
1266  size_t length;
1267  Asn1Tag tag;
1268 
1269  //Length of the ASN.1 structure
1270  length = 0;
1271 
1272  //Add custom attributes, if any
1273  for(i = 0; i < unauthenticatedAttributes->numCustomAttributes; i++)
1274  {
1275  //Encode the attribute to ASN.1 format
1276  error = pkcs7AddAttribute(&unauthenticatedAttributes->customAttributes[i],
1277  output, &length);
1278  //Any error to report?
1279  if(error)
1280  return error;
1281  }
1282 
1283  //Any attributes written?
1284  if(length > 0)
1285  {
1286  //Implicit tagging shall be used to encode the unauthenticatedAttributes
1287  //structure
1288  tag.constructed = TRUE;
1290  tag.objType = 1;
1291  tag.length = length;
1292 
1293  //Write the corresponding ASN.1 tag
1294  error = asn1InsertHeader(&tag, output, &n);
1295  //Any error to report?
1296  if(error)
1297  return error;
1298 
1299  //Total length of the ASN.1 structure
1300  *written = tag.totalLength;
1301  }
1302  else
1303  {
1304  //The unauthenticatedAttributes field is optional
1305  *written = 0;
1306  }
1307 
1308  //Successful processing
1309  return NO_ERROR;
1310 }
1311 
1312 
1313 /**
1314  * @brief Format attribute
1315  * @param[in] attribute Pointer to the attribute to format
1316  * @param[out] output Buffer where to format the ASN.1 structure
1317  * @param[out] written Length of the resulting ASN.1 structure
1318  * @return Error code
1319  **/
1320 
1321 error_t pkcs7FormatAttribute(const Pkcs7Attribute *attribute, uint8_t *output,
1322  size_t *written)
1323 {
1324  error_t error;
1325  size_t n;
1326  size_t length;
1327  uint8_t *p;
1328  Asn1Tag tag;
1329 
1330  //Point to the buffer where to write the ASN.1 structure
1331  p = output;
1332  //Length of the ASN.1 structure
1333  length = 0;
1334 
1335  //Format attrType field
1336  tag.constructed = FALSE;
1339  tag.length = attribute->oid.length;
1340  tag.value = attribute->oid.value;
1341 
1342  //Write the corresponding ASN.1 tag
1343  error = asn1WriteTag(&tag, FALSE, p, &n);
1344  //Any error to report?
1345  if(error)
1346  return error;
1347 
1348  //Advance data pointer
1349  ASN1_INC_POINTER(p, n);
1350  length += n;
1351 
1352  //Format AttributeValue field
1353  tag.constructed = FALSE;
1355  tag.objType = attribute->type;
1356  tag.length = attribute->data.length;
1357  tag.value = attribute->data.value;
1358 
1359  //Write the corresponding ASN.1 tag
1360  error = asn1WriteTag(&tag, FALSE, p, &n);
1361  //Any error to report?
1362  if(error)
1363  return error;
1364 
1365  //Attribute values are encapsulated within a set
1366  tag.constructed = TRUE;
1368  tag.objType = ASN1_TYPE_SET;
1369  tag.length = n;
1370 
1371  //Write the corresponding ASN.1 tag
1372  error = asn1InsertHeader(&tag, p, &n);
1373  //Any error to report?
1374  if(error)
1375  return error;
1376 
1377  //Get the length of the resulting tag
1378  n = tag.totalLength;
1379 
1380  //The attribute is encapsulated within a sequence
1381  tag.constructed = TRUE;
1384  tag.length = length + n;
1385 
1386  //Write the corresponding ASN.1 tag
1387  error = asn1InsertHeader(&tag, output, &n);
1388  //Any error to report?
1389  if(error)
1390  return error;
1391 
1392  //Total number of bytes that have been written
1393  *written = tag.totalLength;
1394 
1395  //Successful processing
1396  return NO_ERROR;
1397 }
1398 
1399 
1400 /**
1401  * @brief Add attribute
1402  * @param[in] attribute Pointer to the attribute to add
1403  * @param[in] attributes Pointer to the list of attributes
1404  * @param[in,out] length Actual length of the list of attributes
1405  * @return Error code
1406  **/
1407 
1409  size_t *length)
1410 {
1411  error_t error;
1412  size_t i;
1413  size_t n;
1414  uint8_t *p;
1415  Asn1Tag tag;
1416 
1417  //If the output parameter is NULL, then the function calculates the
1418  //length of the ASN.1 structure without copying any data
1419  if(attributes != NULL)
1420  {
1421  //Point to the buffer where to format the new attribute
1422  p = attributes + *length;
1423 
1424  //Encode the attribute to ASN.1 format
1425  error = pkcs7FormatAttribute(attribute, p, &n);
1426  //Any error to report?
1427  if(error)
1428  return error;
1429 
1430  //Loop through the collection of attributes
1431  for(i = 0; i < *length; i += tag.totalLength)
1432  {
1433  //Each attribute is encapsulated within a sequence
1434  error = asn1ReadSequence(attributes + i, *length - i, &tag);
1435  //Failed to decode ASN.1 tag?
1436  if(error)
1437  return error;
1438 
1439  //Sort attributes in ascending order
1440  if(pkcs7CompAttributes(p, n, attributes + i, tag.totalLength) < 0)
1441  {
1442  //Make room for the new attribute
1443  osMemmove(attributes + i + n, attributes + i, *length - i);
1444 
1445  //Encode the attribute to ASN.1 format
1446  error = pkcs7FormatAttribute(attribute, attributes + i, &n);
1447  //Any error to report?
1448  if(error)
1449  return error;
1450 
1451  //We are done
1452  break;
1453  }
1454  }
1455  }
1456  else
1457  {
1458  //Calculate the length of the ASN.1 structure
1459  error = pkcs7FormatAttribute(attribute, NULL, &n);
1460  //Any error to report?
1461  if(error)
1462  return error;
1463  }
1464 
1465  //Update the length of the list of attributes
1466  *length += n;
1467 
1468  //Successful processing
1469  return NO_ERROR;
1470 }
1471 
1472 
1473 /**
1474  * @brief Format recipientInfos structure
1475  * @param[in] prngAlgo PRNG algorithm
1476  * @param[in] prngContext Pointer to the PRNG context
1477  * @param[in] recipientInfos Pointer to the structure to format
1478  * @param[in] recipientCertInfo Recipient's certificate
1479  * @param[in] key Pointer to the encryption key
1480  * @param[in] keyLen Length of the encryption key, in bytes
1481  * @param[out] output Buffer where to format the ASN.1 structure
1482  * @param[out] written Length of the resulting ASN.1 structure
1483  * @return Error code
1484  **/
1485 
1486 error_t pkcs7FormatRecipientInfos(const PrngAlgo *prngAlgo, void *prngContext,
1487  const Pkcs7RecipientInfos *recipientInfos, const X509CertInfo *recipientCertInfo,
1488  const uint8_t *key, size_t keyLen, uint8_t *output, size_t *written)
1489 {
1490  error_t error;
1491  uint_t i;
1492  size_t n;
1493  size_t length;
1494  uint8_t *p;
1495  Asn1Tag tag;
1496 
1497  //Point to the buffer where to write the ASN.1 structure
1498  p = output;
1499  //Length of the ASN.1 structure
1500  length = 0;
1501 
1502  //recipientInfos is a collection of per-recipient information. There must be
1503  //at least one element in the collection (refer to RFC 2315, section 10.1)
1504  for(i = 0; i < recipientInfos->numRecipientInfos; i++)
1505  {
1506  //Format RecipientInfo structure
1507  error = pkcs7FormatRecipientInfo(prngAlgo, prngContext,
1508  &recipientInfos->recipientInfos[i], recipientCertInfo, key, keyLen,
1509  p, &n);
1510  //Any error to report?
1511  if(error)
1512  return error;
1513 
1514  //Advance data pointer
1515  ASN1_INC_POINTER(p, n);
1516  length += n;
1517  }
1518 
1519  //The recipientInfos structure is encapsulated within a set
1520  tag.constructed = TRUE;
1522  tag.objType = ASN1_TYPE_SET;
1523  tag.length = n;
1524 
1525  //Write the corresponding ASN.1 tag
1526  error = asn1InsertHeader(&tag, output, &n);
1527  //Any error to report?
1528  if(error)
1529  return error;
1530 
1531  //Total length of the ASN.1 structure
1532  *written = tag.totalLength;
1533 
1534  //Successful processing
1535  return NO_ERROR;
1536 }
1537 
1538 
1539 /**
1540  * @brief Format RecipientInfo structure
1541  * @param[in] prngAlgo PRNG algorithm
1542  * @param[in] prngContext Pointer to the PRNG context
1543  * @param[in] recipientInfo Pointer to the structure to format
1544  * @param[in] recipientCertInfo Recipient's certificate
1545  * @param[in] key Pointer to the encryption key
1546  * @param[in] keyLen Length of the encryption key, in bytes
1547  * @param[out] output Buffer where to format the ASN.1 structure
1548  * @param[out] written Length of the resulting ASN.1 structure
1549  * @return Error code
1550  **/
1551 
1552 error_t pkcs7FormatRecipientInfo(const PrngAlgo *prngAlgo, void *prngContext,
1553  const Pkcs7RecipientInfo *recipientInfo, const X509CertInfo *recipientCertInfo,
1554  const uint8_t *key, size_t keyLen, uint8_t *output, size_t *written)
1555 {
1556  error_t error;
1557  size_t n;
1558  size_t length;
1559  uint8_t *p;
1560  Asn1Tag tag;
1561 
1562  //Point to the buffer where to write the ASN.1 structure
1563  p = output;
1564  //Length of the ASN.1 structure
1565  length = 0;
1566 
1567  //Format version field
1568  error = asn1WriteInt32(recipientInfo->version, FALSE, p, &n);
1569  //Any error to report?
1570  if(error)
1571  return error;
1572 
1573  //Advance data pointer
1574  ASN1_INC_POINTER(p, n);
1575  length += n;
1576 
1577  //Format issuerAndSerialNumber field
1579  p, &n);
1580  //Any error to report?
1581  if(error)
1582  return error;
1583 
1584  //Advance data pointer
1585  ASN1_INC_POINTER(p, n);
1586  length += n;
1587 
1588  //Format keyEncryptionAlgorithm field
1589  error = pkcs7FormatAlgoId(&recipientInfo->keyEncryptionAlgo, p, &n);
1590  //Any error to report?
1591  if(error)
1592  return error;
1593 
1594  //Advance data pointer
1595  ASN1_INC_POINTER(p, n);
1596  length += n;
1597 
1598  //Format encryptedKey field
1599  error = pkcs7FormatEncryptedKey(prngAlgo, prngContext,
1600  recipientCertInfo, key, keyLen, p, &n);
1601  //Any error to report?
1602  if(error)
1603  return error;
1604 
1605  //Advance data pointer
1606  ASN1_INC_POINTER(p, n);
1607  length += n;
1608 
1609  //The RecipientInfo structure is encapsulated within a sequence
1610  tag.constructed = TRUE;
1613  tag.length = length;
1614 
1615  //Write the corresponding ASN.1 tag
1616  error = asn1InsertHeader(&tag, output, &n);
1617  //Any error to report?
1618  if(error)
1619  return error;
1620 
1621  //Total number of bytes that have been written
1622  *written = tag.totalLength;
1623 
1624  //Successful processing
1625  return NO_ERROR;
1626 }
1627 
1628 
1629 /**
1630  * @brief Format encryptedKey structure
1631  * @param[in] prngAlgo PRNG algorithm
1632  * @param[in] prngContext Pointer to the PRNG context
1633  * @param[in] recipientCertInfo Recipient's certificate
1634  * @param[in] key Pointer to the encryption key
1635  * @param[in] keyLen Length of the encryption key, in bytes
1636  * @param[out] output Buffer where to format the ASN.1 structure
1637  * @param[out] written Length of the resulting ASN.1 structure
1638  * @return Error code
1639  **/
1640 
1641 error_t pkcs7FormatEncryptedKey(const PrngAlgo *prngAlgo, void *prngContext,
1642  const X509CertInfo *recipientCertInfo, const uint8_t *key, size_t keyLen,
1643  uint8_t *output, size_t *written)
1644 {
1645  error_t error;
1646  size_t n;
1647  Asn1Tag tag;
1648 
1649  //encryptedKey is the result of encrypting the content-encryption key
1650  //with the recipient's public key (refer to RFC 2315, section 10.2)
1651  error = pkcs7EncryptKey(prngAlgo, prngContext, recipientCertInfo, key,
1652  keyLen, output, &n);
1653  //Any error to report?
1654  if(error)
1655  return error;
1656 
1657  //The encrypted key is encapsulated within an octet string
1658  tag.constructed = FALSE;
1661  tag.length = n;
1662 
1663  //Write the corresponding ASN.1 tag
1664  error = asn1InsertHeader(&tag, output, &n);
1665  //Any error to report?
1666  if(error)
1667  return error;
1668 
1669  //Total length of the ASN.1 structure
1670  *written = tag.totalLength;
1671 
1672  //Successful processing
1673  return NO_ERROR;
1674 }
1675 
1676 
1677 /**
1678  * @brief Format encryptedContentInfo structure
1679  * @param[in] encryptedContentInfo Pointer to the structure to format
1680  * @param[in] key Pointer to the encryption key
1681  * @param[in] keyLen Length of the encryption key, in bytes
1682  * @param[in] plaintext Pointer to the message to be encrypted
1683  * @param[in] plaintextLen Length of the message, in bytes
1684  * @param[out] output Buffer where to format the ASN.1 structure
1685  * @param[out] written Length of the resulting ASN.1 structure
1686  * @return Error code
1687  **/
1688 
1690  const uint8_t *key, size_t keyLen, const uint8_t *plaintext, size_t plaintextLen,
1691  uint8_t *output, size_t *written)
1692 {
1693  error_t error;
1694  size_t n;
1695  size_t length;
1696  uint8_t *p;
1697  Asn1Tag tag;
1698 
1699  //Point to the buffer where to write the ASN.1 structure
1700  p = output;
1701  //Length of the ASN.1 structure
1702  length = 0;
1703 
1704  //Format contentType field
1705  tag.constructed = FALSE;
1708  tag.length = encryptedContentInfo->contentType.length;
1709  tag.value = encryptedContentInfo->contentType.value;
1710 
1711  //Write the corresponding ASN.1 tag
1712  error = asn1WriteTag(&tag, FALSE, p, &n);
1713  //Any error to report?
1714  if(error)
1715  return error;
1716 
1717  //Advance data pointer
1718  ASN1_INC_POINTER(p, n);
1719  length += n;
1720 
1721  //Format contentEncryptionAlgorithm field
1722  error = pkcs7FormatContentEncrAlgo(&encryptedContentInfo->contentEncrAlgo,
1723  p, &n);
1724  //Any error to report?
1725  if(error)
1726  return error;
1727 
1728  //Advance data pointer
1729  ASN1_INC_POINTER(p, n);
1730  length += n;
1731 
1732  //The encryptedContent field is optional, and if the field is not present,
1733  //its intended value must be supplied by other means (refer to RFC 2315,
1734  //section 10.1)
1735  if(plaintextLen > 0)
1736  {
1737  //The encryptedContent field is the result of encrypting the content
1738  error = pkcs7EncryptData(encryptedContentInfo, key, keyLen, plaintext,
1739  plaintextLen, p, &n);
1740  //Any error to report?
1741  if(error)
1742  return error;
1743 
1744  //Explicit tagging shall be used to encode the encryptedContent field
1745  tag.constructed = FALSE;
1747  tag.objType = 0;
1748  tag.length = n;
1749 
1750  //Write the corresponding ASN.1 tag
1751  error = asn1InsertHeader(&tag, p, &n);
1752  //Any error to report?
1753  if(error)
1754  return error;
1755 
1756  //Advance data pointer
1758  length += tag.totalLength;
1759  }
1760 
1761  //The encryptedContentInfo structure is encapsulated within a sequence
1762  tag.constructed = TRUE;
1765  tag.length = length;
1766 
1767  //Write the corresponding ASN.1 tag
1768  error = asn1InsertHeader(&tag, output, &n);
1769  //Any error to report?
1770  if(error)
1771  return error;
1772 
1773  //Total length of the ASN.1 structure
1774  *written = tag.totalLength;
1775 
1776  //Successful processing
1777  return NO_ERROR;
1778 }
1779 
1780 
1781 /**
1782  * @brief Format contentEncryptionAlgorithm structure
1783  * @param[in] contentEncrAlgo Pointer to the structure to format
1784  * @param[out] output Buffer where to format the ASN.1 structure
1785  * @param[out] written Length of the resulting ASN.1 structure
1786  * @return Error code
1787  **/
1788 
1790  uint8_t *output, size_t *written)
1791 {
1792  error_t error;
1793  size_t n;
1794  size_t length;
1795  uint8_t *p;
1796  Asn1Tag tag;
1797 
1798  //Point to the buffer where to write the ASN.1 structure
1799  p = output;
1800  //Length of the ASN.1 structure
1801  length = 0;
1802 
1803  //Format algorithm field
1804  tag.constructed = FALSE;
1807  tag.length = contentEncrAlgo->oid.length;
1808  tag.value = contentEncrAlgo->oid.value;
1809 
1810  //Write the corresponding ASN.1 tag
1811  error = asn1WriteTag(&tag, FALSE, p, &n);
1812  //Any error to report?
1813  if(error)
1814  return error;
1815 
1816  //Advance data pointer
1817  ASN1_INC_POINTER(p, n);
1818  length += n;
1819 
1820  //Format CBCParameter field
1821  tag.constructed = FALSE;
1824  tag.length = contentEncrAlgo->iv.length;
1825  tag.value = contentEncrAlgo->iv.value;
1826 
1827  //Write the corresponding ASN.1 tag
1828  error = asn1WriteTag(&tag, FALSE, p, &n);
1829  //Any error to report?
1830  if(error)
1831  return error;
1832 
1833  //Advance data pointer
1834  ASN1_INC_POINTER(p, n);
1835  length += n;
1836 
1837  //The AlgorithmIdentifier structure is encapsulated within a sequence
1838  tag.constructed = TRUE;
1841  tag.length = length;
1842 
1843  //Write the corresponding ASN.1 tag
1844  error = asn1InsertHeader(&tag, output, &n);
1845  //Any error to report?
1846  if(error)
1847  return error;
1848 
1849  //Total length of the ASN.1 structure
1850  *written = tag.totalLength;
1851 
1852  //Successful processing
1853  return NO_ERROR;
1854 }
1855 
1856 
1857 /**
1858  * @brief Format AlgorithmIdentifier structure
1859  * @param[in] algoId Pointer to the structure to format
1860  * @param[out] output Buffer where to format the ASN.1 structure
1861  * @param[out] written Length of the resulting ASN.1 structure
1862  * @return Error code
1863  **/
1864 
1865 error_t pkcs7FormatAlgoId(const X509AlgoId *algoId, uint8_t *output,
1866  size_t *written)
1867 {
1868  error_t error;
1869  size_t n;
1870  Asn1Tag tag;
1871 
1872  //The algorithm identifier is used to identify a cryptographic algorithm
1873  tag.constructed = FALSE;
1876  tag.length = algoId->oid.length;
1877  tag.value = algoId->oid.value;
1878 
1879  //Write the corresponding ASN.1 tag
1880  error = asn1WriteTag(&tag, FALSE, output, &n);
1881  //Any error to report?
1882  if(error)
1883  return error;
1884 
1885  //The AlgorithmIdentifier structure is encapsulated within a sequence
1886  tag.constructed = TRUE;
1889  tag.length = n;
1890 
1891  //Write the corresponding ASN.1 tag
1892  error = asn1InsertHeader(&tag, output, &n);
1893  //Any error to report?
1894  if(error)
1895  return error;
1896 
1897  //Total length of the ASN.1 structure
1898  *written = tag.totalLength;
1899 
1900  //Successful processing
1901  return NO_ERROR;
1902 }
1903 
1904 #endif
@ ASN1_TYPE_UTC_TIME
Definition: asn1.h:90
@ ASN1_TYPE_GENERALIZED_TIME
Definition: asn1.h:91
error_t x509FormatTimeString(const DateTime *dateTime, uint_t type, char_t *output)
Format UTCTime or GeneralizedTime string.
X509OctetString oid
Definition: pkcs7_common.h:226
Pkcs7Attribute customAttributes[PKCS7_MAX_CUSTOM_ATTRIBUTES]
Definition: pkcs7_common.h:255
error_t pkcs7FormatEnvelopedData(const PrngAlgo *prngAlgo, void *prngContext, const X509CertInfo *recipientCertInfo, const Pkcs7EnvelopedData *envelopedData, const uint8_t *plaintext, size_t plaintextLen, uint8_t *output, size_t *written)
Format enveloped-data content.
Definition: pkcs7_format.c:349
error_t pkcs7FormatContentEncrAlgo(const Pkcs7ContentEncrAlgo *contentEncrAlgo, uint8_t *output, size_t *written)
Format contentEncryptionAlgorithm structure.
X509SerialNumber serialNumber
Definition: pkcs7_common.h:216
const uint8_t MD5_WITH_RSA_ENCRYPTION_OID[9]
Definition: rsa.c:59
const uint8_t SHA512_WITH_RSA_ENCRYPTION_OID[9]
Definition: rsa.c:69
Pkcs7Certificates certificates
Definition: pkcs7_common.h:355
#define PrngAlgo
Definition: crypto.h:980
OID (Object Identifier)
uint8_t p
Definition: ndp.h:300
uint16_t year
Definition: date_time.h:48
Pkcs7AuthenticatedAttributes authenticatedAttributes
Definition: pkcs7_common.h:268
#define TRUE
Definition: os_port.h:50
X509OctetString messageDigest
Definition: pkcs7_common.h:240
error_t asn1InsertHeader(Asn1Tag *tag, uint8_t *data, size_t *written)
Insert an ASN.1 tag header.
Definition: asn1.c:643
X509OctetString contentType
Definition: pkcs7_common.h:340
X509OctetString raw
Definition: pkcs7_common.h:203
error_t pkcs7FormatRecipientInfo(const PrngAlgo *prngAlgo, void *prngContext, const Pkcs7RecipientInfo *recipientInfo, const X509CertInfo *recipientCertInfo, const uint8_t *key, size_t keyLen, uint8_t *output, size_t *written)
Format RecipientInfo structure.
Pkcs7ContentInfo contentInfo
Definition: pkcs7_common.h:354
X509OctetString certificates[PKCS7_MAX_CERTIFICATES]
Definition: pkcs7_common.h:193
uint8_t attributes[]
Definition: radius.h:88
X509OctetString iv
Definition: pkcs7_common.h:330
Content information.
Definition: pkcs7_common.h:317
error_t pkcs7FormatContentInfo(const Pkcs7ContentInfo *contentInfo, uint8_t *output, size_t *written)
Format contentInfo structure.
Definition: pkcs7_format.c:57
error_t pkcs7FormatIssuerAndSerialNumber(const Pkcs7IssuerAndSerialNumber *issuerAndSerialNumber, uint8_t *output, size_t *written)
Format IssuerAndSerialNumber structure.
Definition: pkcs7_format.c:899
Pkcs7Crls crls
Definition: pkcs7_common.h:356
Pkcs7UnauthenticatedAttributes unauthenticatedAttributes
Definition: pkcs7_common.h:271
#define osStrlen(s)
Definition: os_port.h:168
const uint8_t RSASSA_PSS_OID[9]
Definition: rsa.c:85
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:52
X509OctetString crls[PKCS7_MAX_CRLS]
Definition: pkcs7_common.h:205
X509OctetString data
Definition: pkcs7_common.h:228
uint8_t oid[]
Definition: lldp_tlv.h:300
X.509 certificate formatting.
Content encryption algorithm.
Definition: pkcs7_common.h:328
const uint8_t PKCS9_CONTENT_TYPE_OID[9]
Definition: pkcs7_common.c:63
error_t pkcs7EncryptData(const Pkcs7EncryptedContentInfo *encryptedContentInfo, const uint8_t *key, size_t keyLen, const uint8_t *plaintext, size_t plaintextLen, uint8_t *ciphertext, size_t *ciphertextLen)
Perform data encryption.
error_t pkcs7FormatEncryptedDigest(const PrngAlgo *prngAlgo, void *prngContext, const uint8_t *digest, const Pkcs7SignerInfo *signerInfo, const void *signerPrivateKey, uint8_t *output, size_t *written)
Format encryptedDigest structure.
error_t pkcs7FormatUnauthenticatedAttributes(const Pkcs7UnauthenticatedAttributes *unauthenticatedAttributes, uint8_t *output, size_t *written)
Format unauthenticatedAttributes structure.
error_t pkcs7EncryptKey(const PrngAlgo *prngAlgo, void *prngContext, const X509CertInfo *recipientCertInfo, const uint8_t *plaintext, size_t plaintextLen, uint8_t *ciphertext, size_t *ciphertextLen)
Perform key encryption.
const uint8_t SHA384_WITH_RSA_ENCRYPTION_OID[9]
Definition: rsa.c:67
size_t totalLength
Definition: asn1.h:111
size_t length
Definition: asn1.h:109
#define MAX_HASH_DIGEST_SIZE
#define FALSE
Definition: os_port.h:46
Pkcs7RecipientInfos recipientInfos
Definition: pkcs7_common.h:368
error_t pkcs7FormatSignerInfos(const PrngAlgo *prngAlgo, void *prngContext, const Pkcs7SignerInfos *signerInfos, const void *signerPrivateKey, uint8_t *output, size_t *written)
Format SignerInfos structure.
Definition: pkcs7_format.c:697
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
X.509 certificate.
Definition: x509_common.h:1119
error_t
Error codes.
Definition: error.h:43
Encrypted content information.
Definition: pkcs7_common.h:339
error_t pkcs7DigestAuthenticatedAttributes(const Pkcs7SignerInfo *signerInfo, const uint8_t *data, size_t length, uint8_t *digest)
Digest the DER encoding of the authenticatedAttributes field.
Definition: pkcs7_common.c:382
uint8_t algoId[]
Definition: ike.h:1537
Signer information.
Definition: pkcs7_common.h:264
X509OctetString contentType
Definition: pkcs7_common.h:318
X509AlgoId keyEncryptionAlgo
Definition: pkcs7_common.h:295
error_t pkcs7FormatAttribute(const Pkcs7Attribute *attribute, uint8_t *output, size_t *written)
Format attribute.
int_t pkcs7CompAttributes(const uint8_t *attribute1, size_t attributeLen1, const uint8_t *attribute2, size_t attributeLen2)
Compare attributes.
Definition: pkcs7_common.c:329
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
error_t pkcs7FormatAuthenticatedAttributes(const Pkcs7AuthenticatedAttributes *authenticatedAttributes, uint8_t *output, size_t *written)
Format authenticatedAttributes structure.
Definition: pkcs7_format.c:962
X509AlgoId identifiers[PKCS7_MAX_DIGEST_ALGO_IDENTIFIERS]
Definition: pkcs7_common.h:181
ASN.1 tag.
Definition: asn1.h:105
#define ASN1_INC_POINTER(p, n)
Definition: asn1.h:58
error_t pkcs7FormatAlgoId(const X509AlgoId *algoId, uint8_t *output, size_t *written)
Format AlgorithmIdentifier structure.
uint_t pkcs7GetKeyLength(const uint8_t *oid, size_t length)
Get the encryption key length to be used for PBES2 operation.
Definition: pkcs7_common.c:270
const uint8_t PKCS9_MESSAGE_DIGEST_OID[9]
Definition: pkcs7_common.c:65
General definitions for cryptographic algorithms.
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
uint_t numCrls
Definition: pkcs7_common.h:204
Pkcs7Attribute customAttributes[PKCS7_MAX_CUSTOM_ATTRIBUTES]
Definition: pkcs7_common.h:243
uint_t objClass
Definition: asn1.h:107
uint8_t length
Definition: tcp.h:375
Pkcs7DigestAlgos digestAlgos
Definition: pkcs7_common.h:353
X509OctetString oid
Definition: x509_common.h:1089
Recipient information.
Definition: pkcs7_common.h:292
Collection of digest algorithm identifiers.
Definition: pkcs7_common.h:179
Pkcs7EncryptedContentInfo encryptedContentInfo
Definition: pkcs7_common.h:369
Pkcs7IssuerAndSerialNumber issuerAndSerialNumber
Definition: pkcs7_common.h:266
error_t pkcs7FormatEncryptedKey(const PrngAlgo *prngAlgo, void *prngContext, const X509CertInfo *recipientCertInfo, const uint8_t *key, size_t keyLen, uint8_t *output, size_t *written)
Format encryptedKey structure.
const uint8_t SHA256_WITH_RSA_ENCRYPTION_OID[9]
Definition: rsa.c:65
error_t pkcs7FormatSignerInfo(const PrngAlgo *prngAlgo, void *prngContext, const Pkcs7SignerInfo *signerInfo, const void *signerPrivateKey, uint8_t *output, size_t *written)
Format SignerInfo structure.
Definition: pkcs7_format.c:761
const uint8_t RSA_ENCRYPTION_OID[9]
Definition: rsa.c:54
Pkcs7ContentEncrAlgo contentEncrAlgo
Definition: pkcs7_common.h:341
PKCS #7 message encryption.
const uint8_t PKCS7_DATA_OID[9]
Definition: pkcs7_common.c:50
Signed data content.
Definition: pkcs7_common.h:351
Collection of signer informations.
Definition: pkcs7_common.h:280
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:75
Issuer and serial number.
Definition: pkcs7_common.h:214
char char_t
Definition: compiler_port.h:55
error_t pkcs7FormatCertificates(const Pkcs7Certificates *certificates, uint8_t *output, size_t *written)
Format certificates.
Definition: pkcs7_format.c:525
X509OctetString oid
Definition: pkcs7_common.h:329
X509AlgoId digestAlgo
Definition: pkcs7_common.h:267
error_t pkcs7FormatSignedData(const PrngAlgo *prngAlgo, void *prngContext, const Pkcs7SignedData *signedData, const void *signerPrivateKey, uint8_t *output, size_t *written)
Format signed-data content.
Definition: pkcs7_format.c:205
error_t pkcs7GenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, const uint8_t *digest, const Pkcs7SignerInfo *signerInfo, const void *privateKey, uint8_t *output, size_t *written)
Signature generation.
X509SignAlgoId digestEncryptionAlgo
Definition: pkcs7_common.h:269
@ ERROR_UNSUPPORTED_CIPHER_ALGO
Definition: error.h:129
#define OID_COMP(oid1, oidLen1, oid2)
Definition: oid.h:42
uint8_t n
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
X509OctetString content
Definition: pkcs7_common.h:319
error_t x509FormatName(const X509Name *name, uint8_t *output, size_t *written)
Format Name structure.
Unauthenticated attributes.
Definition: pkcs7_common.h:252
error_t pkcs7FormatDigestEncryptionAlgo(const X509SignAlgoId *digestEncryptionAlgo, uint8_t *output, size_t *written)
Format digestEncryptionAlgorithm structure.
const uint8_t PKCS9_SIGNING_TIME_OID[9]
Definition: pkcs7_common.c:67
Pkcs7RecipientInfo recipientInfos[PKCS7_MAX_RECIPIENT_INFOS]
Definition: pkcs7_common.h:308
error_t pkcs7FormatCrls(const Pkcs7Crls *crls, uint8_t *output, size_t *written)
Format CRLs.
Definition: pkcs7_format.c:610
uint8_t oidLen
Definition: lldp_tlv.h:299
Pkcs7SignerInfos signerInfos
Definition: pkcs7_common.h:357
Collection of CRLs.
Definition: pkcs7_common.h:202
Pkcs7SignerInfo signerInfos[PKCS7_MAX_SIGNER_INFOS]
Definition: pkcs7_common.h:283
bool_t constructed
Definition: asn1.h:106
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:77
Collection of certificates.
Definition: pkcs7_common.h:190
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:83
X509OctetString raw
Definition: pkcs7_common.h:191
const uint8_t SHA224_WITH_RSA_ENCRYPTION_OID[9]
Definition: rsa.c:63
const uint8_t * value
Definition: x509_common.h:702
error_t x509FormatSerialNumber(const PrngAlgo *prngAlgo, void *prngContext, const X509SerialNumber *serialNumber, uint8_t *output, size_t *written)
Format SerialNumber field.
PKCS #7 signature generation.
@ ERROR_UNSUPPORTED_SIGNATURE_ALGO
Definition: error.h:132
Authenticated attributes.
Definition: pkcs7_common.h:237
error_t pkcs7FormatEncryptedContentInfo(const Pkcs7EncryptedContentInfo *encryptedContentInfo, const uint8_t *key, size_t keyLen, const uint8_t *plaintext, size_t plaintextLen, uint8_t *output, size_t *written)
Format encryptedContentInfo structure.
PKCS #7 message formatting.
unsigned int uint_t
Definition: compiler_port.h:57
error_t pkcs7AddAttribute(const Pkcs7Attribute *attribute, uint8_t *attributes, size_t *length)
Add attribute.
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:163
error_t pkcs7FormatDigestAlgos(const Pkcs7DigestAlgos *digestAlgos, uint8_t *output, size_t *written)
Format digestAlgos structure.
Definition: pkcs7_format.c:466
error_t asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data, size_t *written)
Write a 32-bit integer to the output stream.
Definition: asn1.c:781
Collection of recipient informations.
Definition: pkcs7_common.h:305
Pkcs7IssuerAndSerialNumber issuerAndSerialNumber
Definition: pkcs7_common.h:294
Enveloped data content.
Definition: pkcs7_common.h:366
X509RsaPssParameters rsaPssParams
Definition: x509_common.h:1091
@ ASN1_TYPE_SET
Definition: asn1.h:84
const uint8_t SHA1_WITH_RSA_ENCRYPTION_OID[9]
Definition: rsa.c:61
error_t pkcs7FormatRecipientInfos(const PrngAlgo *prngAlgo, void *prngContext, const Pkcs7RecipientInfos *recipientInfos, const X509CertInfo *recipientCertInfo, const uint8_t *key, size_t keyLen, uint8_t *output, size_t *written)
Format recipientInfos structure.
const uint8_t * value
Definition: asn1.h:110
Signature algorithm identifier.
Definition: x509_common.h:1088
Algorithm identifier.
Definition: x509_common.h:774
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:108
error_t x509FormatRsaPssParameters(const X509RsaPssParameters *rsaPssParams, uint8_t *output, size_t *written)
Format RSASSA-PSS parameters.
#define osMemmove(dest, src, length)
Definition: os_port.h:150
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_NULL
Definition: asn1.h:76
Attribute.
Definition: pkcs7_common.h:225