ocsp_req_format.c
Go to the documentation of this file.
1 /**
2  * @file ocsp_req_format.c
3  * @brief OCSP request formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL OCSP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ocsp/ocsp_req_format.h"
36 #include "encoding/asn1.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (OCSP_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Format OCSPRequest structure
45  * @param[in] request Pointer to the OCSPRequest structure
46  * @param[out] output Buffer where to store the ASN.1 structure
47  * @param[out] written Length of the resulting ASN.1 structure
48  * @return Error code
49  **/
50 
51 error_t ocspFormatRequest(const OcspRequest *request, uint8_t *output,
52  size_t *written)
53 {
54  error_t error;
55  size_t n;
56  Asn1Tag tag;
57 
58  //Format TBSRequest structure
59  error = ocspFormatTbsRequest(&request->tbsRequest, output, &n);
60  //Any error to report?
61  if(error)
62  return error;
63 
64  //The OCSPRequest structure is encapsulated within a sequence
65  tag.constructed = TRUE;
68  tag.length = n;
69  tag.value = output;
70 
71  //Write the corresponding ASN.1 tag
72  error = asn1WriteTag(&tag, FALSE, output, &n);
73  //Any error to report?
74  if(error)
75  return error;
76 
77  //Total number of bytes that have been written
78  *written = n;
79 
80  //Successful processing
81  return NO_ERROR;
82 }
83 
84 
85 /**
86  * @brief Format TBSRequest structure
87  * @param[in] tbsRequest Pointer to the TBSRequest structure
88  * @param[out] output Buffer where to store the ASN.1 structure
89  * @param[out] written Length of the resulting ASN.1 structure
90  * @return Error code
91  **/
92 
93 error_t ocspFormatTbsRequest(const OcspTbsRequest *tbsRequest, uint8_t *output,
94  size_t *written)
95 {
96  error_t error;
97  size_t n;
98  size_t length;
99  uint8_t *p;
100  Asn1Tag tag;
101 
102  //Point to the buffer where to write the ASN.1 structure
103  p = output;
104  //Length of the ASN.1 structure
105  length = 0;
106 
107  //Format Version field
108  error = ocspFormatVersion(tbsRequest->version, p, &n);
109  //Any error to report?
110  if(error)
111  return error;
112 
113  //Advance data pointer
114  p += n;
115  length += n;
116 
117  //Format RequestList structure
118  error = ocspFormatRequestList(tbsRequest->requestList,
119  tbsRequest->numRequests, p, &n);
120  //Any error to report?
121  if(error)
122  return error;
123 
124  //Advance data pointer
125  p += n;
126  length += n;
127 
128  //Format RequestExtensions structure
129  error = ocspFormatRequestExtensions(&tbsRequest->requestExtensions, p, &n);
130  //Any error to report?
131  if(error)
132  return error;
133 
134  //Advance data pointer
135  p += n;
136  length += n;
137 
138  //The TBSRequest structure is encapsulated within a sequence
139  tag.constructed = TRUE;
142  tag.length = length;
143  tag.value = output;
144 
145  //Write the corresponding ASN.1 tag
146  error = asn1WriteTag(&tag, FALSE, output, &n);
147  //Any error to report?
148  if(error)
149  return error;
150 
151  //Total number of bytes that have been written
152  *written = n;
153 
154  //Successful processing
155  return NO_ERROR;
156 }
157 
158 
159 /**
160  * @brief Format Version field
161  * @param[in] version Version number
162  * @param[out] output Buffer where to format the ASN.1 structure
163  * @param[out] written Length of the resulting ASN.1 structure
164  * @return Error code
165  **/
166 
168  size_t *written)
169 {
170  error_t error;
171  size_t n;
172  Asn1Tag tag;
173 
174  //Encode the version number
175  error = asn1WriteInt32(version, FALSE, output, &n);
176  //Any error to report?
177  if(error)
178  return error;
179 
180  //Explicit tagging shall be used to encode version
181  tag.constructed = TRUE;
183  tag.objType = 0;
184  tag.length = n;
185  tag.value = output;
186 
187  //Write the corresponding ASN.1 tag
188  error = asn1WriteTag(&tag, FALSE, output, &n);
189  //Any error to report?
190  if(error)
191  return error;
192 
193  //Total number of bytes that have been written
194  *written = n;
195 
196  //Successful processing
197  return NO_ERROR;
198 }
199 
200 
201 /**
202  * @brief Format RequestList structure
203  * @param[in] requestList List of requests
204  * @param[in] numRequests Number of requests in the list
205  * @param[out] output Buffer where to store the ASN.1 structure
206  * @param[out] written Length of the resulting ASN.1 structure
207  * @return Error code
208  **/
209 
211  uint_t numRequests, uint8_t *output, size_t *written)
212 {
213  error_t error;
214  uint_t i;
215  size_t n;
216  size_t length;
217  uint8_t *p;
218  Asn1Tag tag;
219 
220  //Point to the buffer where to write the ASN.1 structure
221  p = output;
222  //Length of the ASN.1 structure
223  length = 0;
224 
225  //The RequestList structure contains one or more single certificate status
226  //requests
227  for(i = 0; i < numRequests; i++)
228  {
229  //Format Request structure
230  error = ocspFormatSingleRequest(&requestList[i], p, &n);
231  //Any error to report?
232  if(error)
233  return error;
234 
235  //Advance data pointer
236  p += n;
237  length += n;
238  }
239 
240  //The RequestList structure is encapsulated within a sequence
241  tag.constructed = TRUE;
244  tag.length = length;
245  tag.value = output;
246 
247  //Write the corresponding ASN.1 tag
248  error = asn1WriteTag(&tag, FALSE, output, &n);
249  //Any error to report?
250  if(error)
251  return error;
252 
253  //Total number of bytes that have been written
254  *written = n;
255 
256  //Successful processing
257  return NO_ERROR;
258 }
259 
260 
261 /**
262  * @brief Format Request structure
263  * @param[in] singleRequest Pointer to the Request structure
264  * @param[out] output Buffer where to store the ASN.1 structure
265  * @param[out] written Length of the resulting ASN.1 structure
266  * @return Error code
267  **/
268 
270  uint8_t *output, size_t *written)
271 {
272  error_t error;
273  size_t n;
274  Asn1Tag tag;
275 
276  //Format CertID structure
277  error = ocspFormatCertId(&singleRequest->reqCert, output, &n);
278  //Any error to report?
279  if(error)
280  return error;
281 
282  //The CertID structure is encapsulated within a sequence
283  tag.constructed = TRUE;
286  tag.length = n;
287  tag.value = output;
288 
289  //Write the corresponding ASN.1 tag
290  error = asn1WriteTag(&tag, FALSE, output, &n);
291  //Any error to report?
292  if(error)
293  return error;
294 
295  //Total number of bytes that have been written
296  *written = n;
297 
298  //Successful processing
299  return NO_ERROR;
300 }
301 
302 
303 /**
304  * @brief Format CertID structure
305  * @param[in] certId Pointer to the CertID structure
306  * @param[out] output Buffer where to store the ASN.1 structure
307  * @param[out] written Length of the resulting ASN.1 structure
308  * @return Error code
309  **/
310 
311 error_t ocspFormatCertId(const OcspCertId *certId, uint8_t *output,
312  size_t *written)
313 {
314  error_t error;
315  size_t n;
316  size_t length;
317  uint8_t *p;
318  Asn1Tag tag;
319 
320  //Point to the buffer where to write the ASN.1 structure
321  p = output;
322  //Length of the ASN.1 structure
323  length = 0;
324 
325  //The HashAlgorithm field specifies the hash algorithm used to generate the
326  //issuerNameHash and issuerKeyHash values
327  error = ocspFormatHashAlgo(certId, p, &n);
328  //Any error to report?
329  if(error)
330  return error;
331 
332  //Advance data pointer
333  p += n;
334  length += n;
335 
336  //Format IssuerNameHash field
337  tag.constructed = FALSE;
340  tag.length = certId->issuerNameHash.length;
341  tag.value = certId->issuerNameHash.value;
342 
343  //Write the corresponding ASN.1 tag
344  error = asn1WriteTag(&tag, FALSE, p, &n);
345  //Any error to report?
346  if(error)
347  return error;
348 
349  //Advance data pointer
350  p += n;
351  length += n;
352 
353  //Format IssuerKeyHash field
354  tag.constructed = FALSE;
357  tag.length = certId->issuerKeyHash.length;
358  tag.value = certId->issuerKeyHash.value;
359 
360  //Write the corresponding ASN.1 tag
361  error = asn1WriteTag(&tag, FALSE, p, &n);
362  //Any error to report?
363  if(error)
364  return error;
365 
366  //Advance data pointer
367  p += n;
368  length += n;
369 
370  //The SerialNumber field is the serial number of the certificate for which
371  //status is being requested
372  tag.constructed = FALSE;
375  tag.length = certId->serialNumber.length;
376  tag.value = certId->serialNumber.value;
377 
378  //Write the corresponding ASN.1 tag
379  error = asn1WriteTag(&tag, FALSE, p, &n);
380  //Any error to report?
381  if(error)
382  return error;
383 
384  //Advance data pointer
385  p += n;
386  length += n;
387 
388  //The CertID structure is encapsulated within a sequence
389  tag.constructed = TRUE;
392  tag.length = length;
393  tag.value = output;
394 
395  //Write the corresponding ASN.1 tag
396  error = asn1WriteTag(&tag, FALSE, output, &n);
397  //Any error to report?
398  if(error)
399  return error;
400 
401  //Total number of bytes that have been written
402  *written = n;
403 
404  //Successful processing
405  return NO_ERROR;
406 }
407 
408 
409 /**
410  * @brief Format HashAlgorithm structure
411  * @param[in] certId Pointer to the CertID structure
412  * @param[out] output Buffer where to format the ASN.1 structure
413  * @param[out] written Length of the resulting ASN.1 structure
414  * @return Error code
415  **/
416 
417 error_t ocspFormatHashAlgo(const OcspCertId *certId, uint8_t *output,
418  size_t *written)
419 {
420  error_t error;
421  size_t n;
422  size_t length;
423  uint8_t *p;
424  Asn1Tag tag;
425 
426  //Point to the buffer where to write the ASN.1 structure
427  p = output;
428  //Length of the ASN.1 structure
429  length = 0;
430 
431  //Format hash algorithm OID
432  tag.constructed = FALSE;
435  tag.length = certId->hashAlgo.length;
436  tag.value = certId->hashAlgo.value;
437 
438  //Write the corresponding ASN.1 tag
439  error = asn1WriteTag(&tag, FALSE, p, &n);
440  //Any error to report?
441  if(error)
442  return error;
443 
444  //Advance data pointer
445  p += n;
446  length += n;
447 
448  //The Params field is optional (refer to RFC 5912, section 2)
449  tag.constructed = FALSE;
451  tag.objType = ASN1_TYPE_NULL;
452  tag.length = 0;
453  tag.value = NULL;
454 
455  //Write the corresponding ASN.1 tag
456  error = asn1WriteTag(&tag, FALSE, p, &n);
457  //Any error to report?
458  if(error)
459  return error;
460 
461  //Advance data pointer
462  p += n;
463  length += n;
464 
465  //Write the corresponding ASN.1 tag
466  error = asn1WriteTag(&tag, FALSE, p, &n);
467 
468  //The AlgorithmIdentifier structure is encapsulated within a sequence
469  tag.constructed = TRUE;
472  tag.length = length;
473  tag.value = output;
474 
475  //Write the corresponding ASN.1 tag
476  error = asn1WriteTag(&tag, FALSE, output, &n);
477  //Any error to report?
478  if(error)
479  return error;
480 
481  //Total number of bytes that have been written
482  *written = n;
483 
484  //Successful processing
485  return NO_ERROR;
486 }
487 
488 
489 /**
490  * @brief Format RequestExtensions structure
491  * @param[in] extensions Pointer to the RequestExtensions structure
492  * @param[out] output Buffer where to store the ASN.1 structure
493  * @param[out] written Length of the resulting ASN.1 structure
494  * @return Error code
495  **/
496 
498  uint8_t *output, size_t *written)
499 {
500  error_t error;
501  size_t n;
502  size_t length;
503  uint8_t *p;
504  Asn1Tag tag;
505 
506  //Point to the buffer where to write the ASN.1 structure
507  p = output;
508  //Length of the ASN.1 structure
509  length = 0;
510 
511  //The Nonce extension is used to cryptographically binds a request and a
512  //response to prevent replay attacks (refer to RFC 8954, section 2.1)
513  error = ocspFormatNonceExtension(&extensions->nonce, p, &n);
514  //Any error to report?
515  if(error)
516  return error;
517 
518  //Advance data pointer
519  p += n;
520  length += n;
521 
522  //Any extensions written?
523  if(length > 0)
524  {
525  //The extensions are encapsulated within a sequence
526  tag.constructed = TRUE;
529  tag.length = length;
530  tag.value = output;
531 
532  //Write the corresponding ASN.1 tag
533  error = asn1WriteTag(&tag, FALSE, output, &n);
534  //Any error to report?
535  if(error)
536  return error;
537 
538  //Explicit tagging shall be used to encode the Extensions structure
539  tag.constructed = TRUE;
541  tag.objType = 2;
542  tag.length = n;
543  tag.value = output;
544 
545  //Write the corresponding ASN.1 tag
546  error = asn1WriteTag(&tag, FALSE, output, &length);
547  //Any error to report?
548  if(error)
549  return error;
550  }
551 
552  //Total number of bytes that have been written
553  *written = length;
554 
555  //Successful processing
556  return NO_ERROR;
557 }
558 
559 
560 /**
561  * @brief Format Nonce extension
562  * @param[in] nonce Pointer to the Nonce extension
563  * @param[out] output Buffer where to store the ASN.1 structure
564  * @param[out] written Length of the resulting ASN.1 structure
565  * @return Error code
566  **/
567 
568 error_t ocspFormatNonceExtension(const X509OctetString *nonce, uint8_t *output,
569  size_t *written)
570 {
571  error_t error;
572  size_t n;
573  size_t length;
574  uint8_t *p;
575  Asn1Tag tag;
576 
577  //Point to the buffer where to write the ASN.1 structure
578  p = output;
579  //Length of the ASN.1 structure
580  length = 0;
581 
582  //Valid nonce?
583  if(nonce->value != NULL && nonce->length > 0)
584  {
585  //Format the extension identifier
586  tag.constructed = FALSE;
589  tag.length = sizeof(PKIX_OCSP_NONCE_OID);
591 
592  //Write the corresponding ASN.1 tag
593  error = asn1WriteTag(&tag, FALSE, p, &n);
594  //Any error to report?
595  if(error)
596  return error;
597 
598  //Advance data pointer
599  p += n;
600  length += n;
601 
602  //Format the Nonce field
603  tag.constructed = FALSE;
606  tag.length = nonce->length;
607  tag.value = nonce->value;
608 
609  //Write the corresponding ASN.1 tag
610  error = asn1WriteTag(&tag, FALSE, p, &n);
611  //Any error to report?
612  if(error)
613  return error;
614 
615  //The extension value is encapsulated in an octet string
616  tag.constructed = FALSE;
619  tag.length = n;
620  tag.value = p;
621 
622  //Write the corresponding ASN.1 tag
623  error = asn1WriteTag(&tag, FALSE, p, &n);
624  //Any error to report?
625  if(error)
626  return error;
627 
628  //Adjust the length of the extension
629  length += n;
630 
631  //The extension is encapsulated within a sequence
632  tag.constructed = TRUE;
635  tag.length = length;
636  tag.value = output;
637 
638  //Write the corresponding ASN.1 tag
639  error = asn1WriteTag(&tag, FALSE, output, &length);
640  //Any error to report?
641  if(error)
642  return error;
643  }
644 
645  //Total number of bytes that have been written
646  *written = length;
647 
648  //Successful processing
649  return NO_ERROR;
650 }
651 
652 #endif
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:495
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:74
@ ASN1_TYPE_NULL
Definition: asn1.h:73
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:72
@ ASN1_TYPE_INTEGER
Definition: asn1.h:70
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
uint8_t version
Definition: coap_common.h:177
unsigned int uint_t
Definition: compiler_port.h:50
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t p
Definition: ndp.h:300
const uint8_t PKIX_OCSP_NONCE_OID[9]
Definition: ocsp_common.c:44
OcspVersion
OCSP versions.
Definition: ocsp_common.h:105
error_t ocspFormatCertId(const OcspCertId *certId, uint8_t *output, size_t *written)
Format CertID structure.
error_t ocspFormatTbsRequest(const OcspTbsRequest *tbsRequest, uint8_t *output, size_t *written)
Format TBSRequest structure.
error_t ocspFormatSingleRequest(const OcspSingleRequest *singleRequest, uint8_t *output, size_t *written)
Format Request structure.
error_t ocspFormatNonceExtension(const X509OctetString *nonce, uint8_t *output, size_t *written)
Format Nonce extension.
error_t ocspFormatVersion(OcspVersion version, uint8_t *output, size_t *written)
Format Version field.
error_t ocspFormatRequestExtensions(const OcspExtensions *extensions, uint8_t *output, size_t *written)
Format RequestExtensions structure.
error_t ocspFormatRequestList(const OcspSingleRequest *requestList, uint_t numRequests, uint8_t *output, size_t *written)
Format RequestList structure.
error_t ocspFormatRequest(const OcspRequest *request, uint8_t *output, size_t *written)
Format OCSPRequest structure.
error_t ocspFormatHashAlgo(const OcspCertId *certId, uint8_t *output, size_t *written)
Format HashAlgorithm structure.
OCSP request formatting.
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
ASN.1 tag.
Definition: asn1.h:102
const uint8_t * value
Definition: asn1.h:107
uint_t objClass
Definition: asn1.h:104
uint_t objType
Definition: asn1.h:105
bool_t constructed
Definition: asn1.h:103
size_t length
Definition: asn1.h:106
CertID structure.
Definition: ocsp_common.h:142
X509OctetString serialNumber
Definition: ocsp_common.h:146
X509OctetString hashAlgo
Definition: ocsp_common.h:143
X509OctetString issuerNameHash
Definition: ocsp_common.h:144
X509OctetString issuerKeyHash
Definition: ocsp_common.h:145
OCSP extensions.
Definition: ocsp_common.h:176
OCSPRequest structure.
Definition: ocsp_common.h:200
OcspTbsRequest tbsRequest
Definition: ocsp_common.h:201
SingleRequest structure.
Definition: ocsp_common.h:165
OcspCertId reqCert
Definition: ocsp_common.h:166
TBSRequest structure.
Definition: ocsp_common.h:187
OcspVersion version
Definition: ocsp_common.h:188
OcspExtensions requestExtensions
Definition: ocsp_common.h:191
uint_t numRequests
Definition: ocsp_common.h:189
OcspSingleRequest requestList[OCSP_MAX_REQUESTS]
Definition: ocsp_common.h:190
Octet string.
Definition: x509_common.h:646
const uint8_t * value
Definition: x509_common.h:647
uint8_t length
Definition: tcp.h:368
uint8_t extensions[]
Definition: tls13_misc.h:300