Skip to content

Commit 8b9825e

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 8b9825e

File tree

6 files changed

+136
-25
lines changed

6 files changed

+136
-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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,37 @@ 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+
393+
MBEDTLS_ASN1_CHK_ADD(len,
394+
(*str_writer)(p, start, (const char *) chal_pw->p, chal_pw->len));
395+
365396
return (int) len;
366397
}
367398

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: 87 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,71 @@ 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+
244+
/* pkcs-9-ub-challengePassword INTEGER ::= pkcs-9-ub-pkcs9String */
245+
if (chal_pw_len > MBEDTLS_X509_MAX_PKCS9_STR) {
246+
return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
247+
}
248+
249+
if (printable == 0) {
250+
ctx->chal_pw.tag = MBEDTLS_ASN1_UTF8_STRING;
251+
} else {
252+
ctx->chal_pw.tag = MBEDTLS_ASN1_PRINTABLE_STRING;
253+
}
254+
255+
ctx->chal_pw.len = chal_pw_len;
256+
ctx->chal_pw.p = chal_pw;
257+
258+
return 0;
259+
}
260+
261+
/*
262+
* RFC 2986 - 4.1 CertificationRequestInfo
263+
*
264+
* Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
265+
*
266+
* CRIAttributes ATTRIBUTE ::= {
267+
* ... -- add any locally defined attributes here -- }
268+
*
269+
* Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
270+
* type ATTRIBUTE.&id({IOSet}),
271+
* values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
272+
* }
273+
*
274+
*/
275+
static int x509write_csr_attribute(unsigned char **p,
276+
unsigned char *start,
277+
const char *oid, size_t oid_len,
278+
size_t val_len)
279+
{
280+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
281+
size_t len = val_len;
282+
283+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
284+
MBEDTLS_ASN1_CHK_ADD(len,
285+
mbedtls_asn1_write_tag(
286+
p, start,
287+
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
288+
289+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
290+
291+
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
292+
MBEDTLS_ASN1_CHK_ADD(len,
293+
mbedtls_asn1_write_tag(
294+
p, start,
295+
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
296+
297+
return (int) (len - val_len);
298+
}
299+
235300
static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
236301
unsigned char *buf,
237302
size_t size,
@@ -255,32 +320,34 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
255320
/* Write the CSR backwards starting from the end of buf */
256321
c = buf + size;
257322

258-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,
259-
ctx->extensions));
323+
if (ctx->extensions != NULL) {
324+
size_t attr_len = 0;
260325

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(
326+
MBEDTLS_ASN1_CHK_ADD(attr_len,
327+
mbedtls_x509_write_extensions(&c, buf, ctx->extensions));
328+
MBEDTLS_ASN1_CHK_ADD(attr_len,
329+
x509write_csr_attribute(
265330
&c, buf,
266-
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
331+
MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
332+
MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ),
333+
attr_len));
267334

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));
335+
len += attr_len;
336+
}
273337

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)));
338+
if (ctx->chal_pw.p != NULL) {
339+
size_t attr_len = 0;
278340

279-
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
280-
MBEDTLS_ASN1_CHK_ADD(len,
281-
mbedtls_asn1_write_tag(
341+
MBEDTLS_ASN1_CHK_ADD(attr_len,
342+
mbedtls_x509_write_challenge_password(&c, buf, &(ctx->chal_pw)));
343+
MBEDTLS_ASN1_CHK_ADD(attr_len,
344+
x509write_csr_attribute(
282345
&c, buf,
283-
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
346+
MBEDTLS_OID_PKCS9_CSR_CHAL_PW,
347+
MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_CHAL_PW),
348+
attr_len));
349+
350+
len += attr_len;
284351
}
285352

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

0 commit comments

Comments
 (0)