x509_csr_create.c
Go to the documentation of this file.
1 /**
2  * @file x509_csr_create.c
3  * @brief CSR (Certificate Signing Request) generation
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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 1.9.6
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 "pkix/x509_cert_create.h"
37 #include "pkix/x509_csr_create.h"
38 #include "pkix/x509_key_format.h"
39 #include "encoding/asn1.h"
40 #include "encoding/oid.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (X509_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Generate a CSR (Certificate Signing Request)
49  * @param[in] prngAlgo PRNG algorithm
50  * @param[in] prngContext Pointer to the PRNG context
51  * @param[in] certReqInfo Certificate request information
52  * @param[in] subjectPublicKey Pointer to the subject's public key
53  * @param[in] signatureAlgo Signature algorithm
54  * @param[in] signerPrivateKey Pointer to the subject's private key
55  * @param[out] output Buffer where to store the CSR
56  * @param[out] written Length of the resulting CSR
57  * @return Error code
58  **/
59 
60 error_t x509CreateCsr(const PrngAlgo *prngAlgo, void *prngContext,
61  const X509CertRequestInfo *certReqInfo, const void *subjectPublicKey,
62  const X509SignatureAlgoId *signatureAlgo, const void *signerPrivateKey,
63  uint8_t *output, size_t *written)
64 {
65  error_t error;
66  size_t n;
67  size_t length;
68  uint8_t *p;
69  uint8_t *input;
70  size_t inputLen;
71  Asn1Tag tag;
72 
73  //Check parameters
74  if(certReqInfo == NULL || subjectPublicKey == NULL ||
75  signatureAlgo == NULL || signerPrivateKey == NULL || written == NULL)
76  {
78  }
79 
80  //Point to the buffer where to write the CSR
81  p = output;
82  //Length of the CSR
83  length = 0;
84 
85  //Format CertificationRequestInfo structure
86  error = x509FormatCertRequestInfo(certReqInfo, subjectPublicKey, p, &n);
87  //Any error to report?
88  if(error)
89  return error;
90 
91  //The ASN.1 DER-encoded CertificationRequestInfo is used as the input to
92  //the signature function
93  input = p;
94  inputLen = n;
95 
96  //Advance data pointer
97  p += n;
98  length += n;
99 
100  //Format SignatureAlgorithm structure
101  error = x509FormatSignatureAlgo(signatureAlgo, p, &n);
102  //Any error to report?
103  if(error)
104  return error;
105 
106  //Advance data pointer
107  p += n;
108  length += n;
109 
110  //Format Signature structure
111  error = x509FormatSignatureValue(prngAlgo, prngContext, input, inputLen,
112  signatureAlgo, &certReqInfo->subjectPublicKeyInfo, signerPrivateKey,
113  p, &n);
114  //Any error to report?
115  if(error)
116  return error;
117 
118  //Advance data pointer
119  p += n;
120  length += n;
121 
122  //The CSR is encapsulated within a sequence
123  tag.constructed = TRUE;
126  tag.length = length;
127  tag.value = output;
128 
129  //Write the corresponding ASN.1 tag
130  error = asn1WriteTag(&tag, FALSE, output, &n);
131  //Any error to report?
132  if(error)
133  return error;
134 
135  //Total number of bytes that have been written
136  *written = n;
137 
138  //Successful processing
139  return NO_ERROR;
140 }
141 
142 
143 /**
144  * @brief Format CertificationRequestInfo structure
145  * @param[in] certReqInfo Certification request information
146  * @param[in] publicKey Pointer to the subject's public key
147  * @param[out] output Buffer where to format the ASN.1 structure
148  * @param[out] written Length of the resulting ASN.1 structure
149  * @return Error code
150  **/
151 
153  const void *publicKey, uint8_t *output, size_t *written)
154 {
155  error_t error;
156  size_t n;
157  size_t length;
158  uint8_t *p;
159  Asn1Tag tag;
160 
161  //Point to the buffer where to write the ASN.1 structure
162  p = output;
163  //Length of the ASN.1 structure
164  length = 0;
165 
166  //Format Version field
167  error = asn1WriteInt32(certReqInfo->version, FALSE, p, &n);
168  //Any error to report?
169  if(error)
170  return error;
171 
172  //Advance data pointer
173  p += n;
174  length += n;
175 
176  //Format Subject field
177  error = x509FormatName(&certReqInfo->subject, p, &n);
178  //Any error to report?
179  if(error)
180  return error;
181 
182  //Advance data pointer
183  p += n;
184  length += n;
185 
186  //Format SubjectPublicKeyInfo field
188  publicKey, NULL, p, &n);
189  //Any error to report?
190  if(error)
191  return error;
192 
193  //Advance data pointer
194  p += n;
195  length += n;
196 
197  //Format Attributes field
198  error = x509FormatAttributes(&certReqInfo->attributes, p, &n);
199  //Any error to report?
200  if(error)
201  return error;
202 
203  //Advance data pointer
204  p += n;
205  length += n;
206 
207  //The CertificationRequestInfo structure is encapsulated within a sequence
208  tag.constructed = TRUE;
211  tag.length = length;
212  tag.value = output;
213 
214  //Write the corresponding ASN.1 tag
215  error = asn1WriteTag(&tag, FALSE, output, &n);
216  //Any error to report?
217  if(error)
218  return error;
219 
220  //Total number of bytes that have been written
221  *written = n;
222 
223  //Successful processing
224  return NO_ERROR;
225 }
226 
227 
228 /**
229  * @brief Format CSR attributes
230  * @param[in] attributes Pointer to the CSR attributes
231  * @param[out] output Buffer where to format the ASN.1 structure
232  * @param[out] written Length of the resulting ASN.1 structure
233  * @return Error code
234  **/
235 
237  uint8_t *output, size_t *written)
238 {
239  error_t error;
240  size_t n;
241  size_t length;
242  uint8_t *p;
243  Asn1Tag tag;
244 
245  //Point to the buffer where to write the ASN.1 structure
246  p = output;
247  //Length of the ASN.1 structure
248  length = 0;
249 
250  //Format PKCS#9 Challenge Password attribute
251  error = x509FormatChallengePassword(&attributes->challengePwd, p, &n);
252  //Any error to report?
253  if(error)
254  return error;
255 
256  //Advance data pointer
257  p += n;
258  length += n;
259 
260  //Format PKCS#9 Extension Request attribute
261  error = x509FormatExtensionRequest(&attributes->extensionReq, p, &n);
262  //Any error to report?
263  if(error)
264  return error;
265 
266  //Advance data pointer
267  p += n;
268  length += n;
269 
270  //Explicit tagging shall be used to encode the Extensions structure
271  tag.constructed = TRUE;
273  tag.objType = 0;
274  tag.length = length;
275  tag.value = output;
276 
277  //Write the corresponding ASN.1 tag
278  error = asn1WriteTag(&tag, FALSE, output, &length);
279  //Any error to report?
280  if(error)
281  return error;
282 
283  //Total number of bytes that have been written
284  *written = length;
285 
286  //Successful processing
287  return NO_ERROR;
288 }
289 
290 
291 /**
292  * @brief Format ChallengePassword attribute
293  * @param[in] challengePwd Value of the attribute
294  * @param[out] output Buffer where to format the ASN.1 structure
295  * @param[out] written Length of the resulting ASN.1 structure
296  * @return Error code
297  **/
298 
300  uint8_t *output, size_t *written)
301 {
302  error_t error;
303  size_t n;
304  size_t length;
305  uint8_t *p;
306  Asn1Tag tag;
307 
308  //Point to the buffer where to write the ASN.1 structure
309  p = output;
310  //Length of the ASN.1 structure
311  length = 0;
312 
313  //Valid challenge password?
314  if(challengePwd->value != NULL && challengePwd->length > 0)
315  {
316  //Format attribute identifier
317  tag.constructed = FALSE;
320  tag.length = sizeof(X509_CHALLENGE_PASSWORD_OID);
322 
323  //Write the corresponding ASN.1 tag
324  error = asn1WriteTag(&tag, FALSE, p, &n);
325  //Any error to report?
326  if(error)
327  return error;
328 
329  //Advance data pointer
330  p += n;
331  length += n;
332 
333  //Format challenge password
334  tag.constructed = FALSE;
337  tag.length = challengePwd->length;
338  tag.value = (uint8_t *) challengePwd->value;
339 
340  //Write the corresponding ASN.1 tag
341  error = asn1WriteTag(&tag, FALSE, p, &n);
342  //Any error to report?
343  if(error)
344  return error;
345 
346  //Attribute value is encapsulated within a set
347  tag.constructed = TRUE;
349  tag.objType = ASN1_TYPE_SET;
350  tag.length = n;
351  tag.value = p;
352 
353  //Write the corresponding ASN.1 tag
354  error = asn1WriteTag(&tag, FALSE, p, &n);
355  //Any error to report?
356  if(error)
357  return error;
358 
359  //The attribute is encapsulated within a sequence
360  tag.constructed = TRUE;
363  tag.length = length + n;
364  tag.value = output;
365 
366  //Write the corresponding ASN.1 tag
367  error = asn1WriteTag(&tag, FALSE, output, &length);
368  //Any error to report?
369  if(error)
370  return error;
371  }
372 
373  //Total number of bytes that have been written
374  *written = length;
375 
376  //Successful processing
377  return NO_ERROR;
378 }
379 
380 
381 /**
382  * @brief Format ExtensionRequest attribute
383  * @param[in] extensionReq Value of the attribute
384  * @param[out] output Buffer where to format the ASN.1 structure
385  * @param[out] written Length of the resulting ASN.1 structure
386  * @return Error code
387  **/
388 
390  uint8_t *output, size_t *written)
391 {
392  error_t error;
393  size_t n;
394  size_t m;
395  size_t length;
396  uint8_t *p;
397  Asn1Tag tag;
398 
399  //Point to the buffer where to write the ASN.1 structure
400  p = output;
401  //Length of the ASN.1 structure
402  length = 0;
403 
404  //Format attribute identifier
405  tag.constructed = FALSE;
408  tag.length = sizeof(X509_EXTENSION_REQUEST_OID);
410 
411  //Write the corresponding ASN.1 tag
412  error = asn1WriteTag(&tag, FALSE, p, &m);
413  //Any error to report?
414  if(error)
415  return error;
416 
417  //Advance data pointer
418  p += m;
419 
420  //Format NetscapeCertType extension
421  error = x509FormatNsCertType(&extensionReq->nsCertType, p, &n);
422  //Any error to report?
423  if(error)
424  return error;
425 
426  //Advance data pointer
427  p += n;
428  length += n;
429 
430  //Format BasicConstraints extension
431  error = x509FormatBasicConstraints(&extensionReq->basicConstraints,
432  p, &n);
433  //Any error to report?
434  if(error)
435  return error;
436 
437  //Advance data pointer
438  p += n;
439  length += n;
440 
441  //Format KeyUsage extension
442  error = x509FormatKeyUsage(&extensionReq->keyUsage, p, &n);
443  //Any error to report?
444  if(error)
445  return error;
446 
447  //Advance data pointer
448  p += n;
449  length += n;
450 
451  //Format SubjectAltName extension
452  error = x509FormatSubjectAltName(&extensionReq->subjectAltName, p, &n);
453  //Any error to report?
454  if(error)
455  return error;
456 
457  //Advance data pointer
458  p += n;
459  length += n;
460 
461  //Format SubjectKeyIdentifier extension
462  error = x509FormatSubjectKeyId(&extensionReq->subjectKeyId, p, &n);
463  //Any error to report?
464  if(error)
465  return error;
466 
467  //Advance data pointer
468  p += n;
469  length += n;
470 
471  //Format AuthorityKeyIdentifier extension
472  error = x509FormatAuthorityKeyId(&extensionReq->authKeyId, p, &n);
473  //Any error to report?
474  if(error)
475  return error;
476 
477  //Advance data pointer
478  p += n;
479  length += n;
480 
481  //Any extensions written?
482  if(length > 0)
483  {
484  //Point to the first certificate extension
485  p = output + m;
486 
487  //Certificate extensions are encapsulated within a sequence
488  tag.constructed = TRUE;
491  tag.length = length;
492  tag.value = p;
493 
494  //Write the corresponding ASN.1 tag
495  error = asn1WriteTag(&tag, FALSE, p, &length);
496  //Any error to report?
497  if(error)
498  return error;
499 
500  //Attribute value is encapsulated within a set
501  tag.constructed = TRUE;
503  tag.objType = ASN1_TYPE_SET;
504  tag.length = length;
505  tag.value = p;
506 
507  //Write the corresponding ASN.1 tag
508  error = asn1WriteTag(&tag, FALSE, p, &length);
509  //Any error to report?
510  if(error)
511  return error;
512 
513  //The attribute is encapsulated within a sequence
514  tag.constructed = TRUE;
517  tag.length = length + m;
518  tag.value = output;
519 
520  //Write the corresponding ASN.1 tag
521  error = asn1WriteTag(&tag, FALSE, output, &length);
522  //Any error to report?
523  if(error)
524  return error;
525  }
526 
527  //Total number of bytes that have been written
528  *written = length;
529 
530  //Successful processing
531  return NO_ERROR;
532 }
533 
534 #endif
uint8_t length
Definition: dtls_misc.h:149
X509AuthorityKeyId authKeyId
Definition: x509_common.h:851
CSR (Certificate Signing Request) generation.
Common interface for pseudo-random number generators.
Definition: crypto.h:1168
Signature algorithm identifier.
Definition: x509_common.h:876
OID (Object Identifier)
uint8_t p
Definition: ndp.h:298
X509KeyUsage keyUsage
Definition: x509_common.h:847
#define TRUE
Definition: os_port.h:50
error_t x509FormatCertRequestInfo(const X509CertRequestInfo *certReqInfo, const void *publicKey, uint8_t *output, size_t *written)
Format CertificationRequestInfo structure.
const char_t * value
Definition: x509_common.h:1096
X509NsCertType nsCertType
Definition: x509_common.h:852
const uint8_t X509_CHALLENGE_PASSWORD_OID[9]
Definition: x509_common.c:159
X509Extensions extensionReq
Definition: x509_common.h:1123
const uint8_t X509_EXTENSION_REQUEST_OID[9]
Definition: x509_common.c:161
error_t x509FormatAttributes(const X509Attributes *attributes, uint8_t *output, size_t *written)
Format CSR attributes.
error_t x509FormatSubjectPublicKeyInfo(const X509SubjectPublicKeyInfo *publicKeyInfo, const void *publicKey, uint8_t *keyId, uint8_t *output, size_t *written)
Format SubjectPublicKeyInfo structure.
size_t length
Definition: asn1.h:102
error_t x509FormatSignatureValue(const PrngAlgo *prngAlgo, void *prngContext, const uint8_t *tbsCert, size_t tbsCertLen, const X509SignatureAlgoId *signatureAlgoId, const X509SubjectPublicKeyInfo *publicKeyInfo, const void *privateKey, uint8_t *output, size_t *written)
Format SignatureValue field.
X509SubjectPublicKeyInfo subjectPublicKeyInfo
Definition: x509_common.h:1137
error_t x509FormatSignatureAlgo(const X509SignatureAlgoId *signatureAlgo, uint8_t *output, size_t *written)
Format SignatureAlgorithm structure.
#define FALSE
Definition: os_port.h:46
error_t x509FormatExtensionRequest(const X509Extensions *extensionReq, uint8_t *output, size_t *written)
Format ExtensionRequest attribute.
Invalid parameter.
Definition: error.h:47
X.509 certificate generation.
error_t
Error codes.
Definition: error.h:42
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:48
X509BasicConstraints basicConstraints
Definition: x509_common.h:845
ASN.1 tag.
Definition: asn1.h:97
error_t x509FormatChallengePassword(const X509ChallengePassword *challengePwd, uint8_t *output, size_t *written)
Format ChallengePassword attribute.
General definitions for cryptographic algorithms.
X509Version version
Definition: x509_common.h:1135
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:377
uint_t objClass
Definition: asn1.h:100
CertificationRequestInfo structure.
Definition: x509_common.h:1131
X509SubjectAltName subjectAltName
Definition: x509_common.h:849
error_t x509FormatKeyUsage(const X509KeyUsage *keyUsage, uint8_t *output, size_t *written)
Format KeyUsage extension.
Formatting of ASN.1 encoded keys.
uint8_t m
Definition: ndp.h:302
uint8_t n
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:50
error_t x509FormatSubjectAltName(const X509SubjectAltName *subjectAltName, uint8_t *output, size_t *written)
Format SubjectAltName extension.
error_t x509FormatName(const X509Name *name, uint8_t *output, size_t *written)
Format Name structure.
CSR attributes.
Definition: x509_common.h:1118
bool_t constructed
Definition: asn1.h:99
error_t x509FormatSubjectKeyId(const X509SubjectKeyId *subjectKeyId, uint8_t *output, size_t *written)
Format SubjectKeyIdentifier extension.
X.509 certificate extensions.
Definition: x509_common.h:841
error_t x509FormatAuthorityKeyId(const X509AuthorityKeyId *authKeyId, uint8_t *output, size_t *written)
Format AuthorityKeyIdentifier extension.
X509ChallengePassword challengePwd
Definition: x509_common.h:1122
error_t x509FormatBasicConstraints(const X509BasicConstraints *basicConstraints, uint8_t *output, size_t *written)
Format BasicConstraints extension.
error_t x509CreateCsr(const PrngAlgo *prngAlgo, void *prngContext, const X509CertRequestInfo *certReqInfo, const void *subjectPublicKey, const X509SignatureAlgoId *signatureAlgo, const void *signerPrivateKey, uint8_t *output, size_t *written)
Generate a CSR (Certificate Signing Request)
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:516
X509SubjectKeyId subjectKeyId
Definition: x509_common.h:850
error_t x509FormatNsCertType(const X509NsCertType *nsCertType, uint8_t *output, size_t *written)
Format NetscapeCertType extension.
X509Attributes attributes
Definition: x509_common.h:1138
const uint8_t * value
Definition: asn1.h:103
PKCS#9 ChallengePassword attribute.
Definition: x509_common.h:1094
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:101
ASN.1 (Abstract Syntax Notation One)