Skip to content

Commit de465b7

Browse files
committed
Support challenge password attribute in CSR
Useful as an extra form of authentication in certificate enrollment/renewal using SCEP [1] or EST [2]. Specified in RFC 2985 [3] as challengePassword ATTRIBUTE ::= { WITH SYNTAX DirectoryString {pkcs-9-ub-challengePassword} EQUALITY MATCHING RULE caseExactMatch SINGLE VALUE TRUE ID pkcs-9-at-challengePassword } Use mbedtls_x509write_csr_set_challenge_password function to set the challenge password in mbedtls_x509write_csr object, either as (text) printable (preferred), or UTF-8 string. resolves #4886 1. https://www.rfc-editor.org/rfc/rfc8894.html#name-challengepassword-shared-se 2. https://www.rfc-editor.org/rfc/rfc7030#section-4.5 3. https://www.rfc-editor.org/rfc/rfc2985#section-5.4 Signed-off-by: Tijs Van Buggenhout <tijs.van.buggenhout@axsguard.com>
1 parent 6942cc3 commit de465b7

File tree

6 files changed

+134
-25
lines changed

6 files changed

+134
-25
lines changed

include/mbedtls/oid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@
320320
/*
321321
* PKCS#8 OIDs
322322
*/
323+
#define MBEDTLS_OID_PKCS9_CSR_CHAL_PW MBEDTLS_OID_PKCS9 "\x07" /**< challenge password OBJECT IDENTIFIER ::= {pkcs-9 7 } */
323324
#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */
324325

325326
/*

include/mbedtls/x509.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
#define MBEDTLS_X509_FORMAT_PEM 2
209209

210210
#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */
211+
#define MBEDTLS_X509_MAX_PKCS9_STR 255 /** pkcs-9-ub-pkcs9String INTEGER ::= 255 */
211212

212213
#ifdef __cplusplus
213214
extern "C" {
@@ -461,6 +462,8 @@ int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
461462
int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
462463
const char *oid, size_t oid_len,
463464
unsigned char *sig, size_t size);
465+
int mbedtls_x509_write_challenge_password(unsigned char **p, unsigned char *start,
466+
mbedtls_asn1_buf *chal_pw);
464467
int mbedtls_x509_get_ns_cert_type(unsigned char **p,
465468
const unsigned char *end,
466469
unsigned char *ns_cert_type);

include/mbedtls/x509_csr.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ typedef struct mbedtls_x509write_csr {
8080
mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject);
8181
mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg);
8282
mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions);
83+
mbedtls_asn1_buf MBEDTLS_PRIVATE(chal_pw);
8384
}
8485
mbedtls_x509write_csr;
8586

@@ -278,6 +279,19 @@ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
278279
int critical,
279280
const unsigned char *val, size_t val_len);
280281

282+
/**
283+
* \brief Set a CSR challenge password
284+
*
285+
* \param ctx CSR context to use
286+
* \param chal_pw challenge password OCTET STRING
287+
* \param chal_pw_len length of the challenge password data
288+
* \param printable tag as printable string (\c 1) or UTF8 string (\c 0)
289+
*
290+
* \return 0 if successful, or a MBEDTLS_ERR_X509_BAD_INPUT_DATA
291+
*/
292+
int mbedtls_x509write_csr_set_challenge_password(mbedtls_x509write_csr *ctx,
293+
unsigned char *chal_pw, size_t chal_pw_len,
294+
int printable);
281295
/**
282296
* \brief Free the contents of a CSR context
283297
*

library/x509_create.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,36 @@ int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,
362362
cur_ext = cur_ext->next;
363363
}
364364

365+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len( p, start, len));
366+
MBEDTLS_ASN1_CHK_ADD(len,
367+
mbedtls_asn1_write_tag(p, start,
368+
MBEDTLS_ASN1_CONSTRUCTED |
369+
MBEDTLS_ASN1_SEQUENCE));
370+
371+
return (int) len;
372+
}
373+
374+
/*
375+
* challengePassword ATTRIBUTE ::= {
376+
* WITH SYNTAX PKCS9String
377+
* EQUALITY MATCHING RULE caseExactMatch
378+
* SINGLE VALUE TRUE
379+
* ID pkcs-9-at-challengePassword
380+
*/
381+
int mbedtls_x509_write_challenge_password(unsigned char **p, unsigned char *start,
382+
mbedtls_asn1_buf *chal_pw )
383+
{
384+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
385+
size_t len = 0;
386+
int (*str_writer)(unsigned char**, const unsigned char*,
387+
const char*, size_t) = &mbedtls_asn1_write_printable_string;
388+
389+
if (chal_pw->tag == MBEDTLS_ASN1_UTF8_STRING)
390+
str_writer = &mbedtls_asn1_write_utf8_string;
391+
392+
MBEDTLS_ASN1_CHK_ADD(len,
393+
(*str_writer)(p, start, (const char *)chal_pw->p, chal_pw->len));
394+
365395
return (int) len;
366396
}
367397

library/x509write_crt.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -468,11 +468,6 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
468468
mbedtls_x509_write_extensions(&c,
469469
buf, ctx->extensions));
470470
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
471-
MBEDTLS_ASN1_CHK_ADD(len,
472-
mbedtls_asn1_write_tag(&c, buf,
473-
MBEDTLS_ASN1_CONSTRUCTED |
474-
MBEDTLS_ASN1_SEQUENCE));
475-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
476471
MBEDTLS_ASN1_CHK_ADD(len,
477472
mbedtls_asn1_write_tag(&c, buf,
478473
MBEDTLS_ASN1_CONTEXT_SPECIFIC |

library/x509write_csr.c

Lines changed: 86 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,68 @@ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,
232232
return 0;
233233
}
234234

235+
int mbedtls_x509write_csr_set_challenge_password(mbedtls_x509write_csr *ctx,
236+
unsigned char *chal_pw,
237+
size_t chal_pw_len,
238+
int printable)
239+
{
240+
if (chal_pw_len == 0 || chal_pw == NULL)
241+
return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
242+
243+
/* pkcs-9-ub-challengePassword INTEGER ::= pkcs-9-ub-pkcs9String */
244+
if (chal_pw_len > MBEDTLS_X509_MAX_PKCS9_STR)
245+
return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
246+
247+
if (printable == 0)
248+
ctx->chal_pw.tag = MBEDTLS_ASN1_UTF8_STRING;
249+
else
250+
ctx->chal_pw.tag = MBEDTLS_ASN1_PRINTABLE_STRING;
251+
252+
ctx->chal_pw.len = chal_pw_len;
253+
ctx->chal_pw.p = chal_pw;
254+
255+
return 0;
256+
}
257+
258+
/*
259+
* RFC 2986 - 4.1 CertificationRequestInfo
260+
*
261+
* Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
262+
*
263+
* CRIAttributes ATTRIBUTE ::= {
264+
* ... -- add any locally defined attributes here -- }
265+
*
266+
* Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
267+
* type ATTRIBUTE.&id({IOSet}),
268+
* values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
269+
* }
270+
*
271+
*/
272+
static int x509write_csr_attribute(unsigned char **p,
273+
unsigned char *start,
274+
const char *oid, size_t oid_len,
275+
size_t val_len)
276+
{
277+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
278+
size_t len = val_len;
279+
280+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len( p, start, len));
281+
MBEDTLS_ASN1_CHK_ADD(len,
282+
mbedtls_asn1_write_tag(
283+
p, start,
284+
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) );
285+
286+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
287+
288+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
289+
MBEDTLS_ASN1_CHK_ADD(len,
290+
mbedtls_asn1_write_tag(
291+
p, start,
292+
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
293+
294+
return (int) (len - val_len);
295+
}
296+
235297
static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
236298
unsigned char *buf,
237299
size_t size,
@@ -255,32 +317,36 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
255317
/* Write the CSR backwards starting from the end of buf */
256318
c = buf + size;
257319

258-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,
259-
ctx->extensions));
320+
if (ctx->extensions != NULL)
321+
{
322+
size_t attr_len = 0;
260323

261-
if (len) {
262-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
263-
MBEDTLS_ASN1_CHK_ADD(len,
264-
mbedtls_asn1_write_tag(
324+
MBEDTLS_ASN1_CHK_ADD(attr_len,
325+
mbedtls_x509_write_extensions(&c, buf, ctx->extensions));
326+
MBEDTLS_ASN1_CHK_ADD(attr_len,
327+
x509write_csr_attribute(
265328
&c, buf,
266-
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
329+
MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
330+
MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ),
331+
attr_len));
267332

268-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
269-
MBEDTLS_ASN1_CHK_ADD(len,
270-
mbedtls_asn1_write_tag(
271-
&c, buf,
272-
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
333+
len += attr_len;
334+
}
273335

274-
MBEDTLS_ASN1_CHK_ADD(len,
275-
mbedtls_asn1_write_oid(
276-
&c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
277-
MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ)));
336+
if (ctx->chal_pw.p != NULL)
337+
{
338+
size_t attr_len = 0;
278339

279-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
280-
MBEDTLS_ASN1_CHK_ADD(len,
281-
mbedtls_asn1_write_tag(
340+
MBEDTLS_ASN1_CHK_ADD(attr_len,
341+
mbedtls_x509_write_challenge_password(&c, buf, &(ctx->chal_pw)));
342+
MBEDTLS_ASN1_CHK_ADD(attr_len,
343+
x509write_csr_attribute(
282344
&c, buf,
283-
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
345+
MBEDTLS_OID_PKCS9_CSR_CHAL_PW,
346+
MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_CHAL_PW),
347+
attr_len));
348+
349+
len += attr_len;
284350
}
285351

286352
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));

0 commit comments

Comments
 (0)