Coverage Report

Created: 2026-10-28 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/x509/x_req.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include <openssl/asn1t.h>
13
#include <openssl/x509.h>
14
#include "crypto/x509.h"
15
16
/*-
17
 * X509_REQ_INFO is handled in an unusual way to get round
18
 * invalid encodings. Some broken certificate requests don't
19
 * encode the attributes field if it is empty. This is in
20
 * violation of PKCS#10 but we need to tolerate it. We do
21
 * this by making the attributes field OPTIONAL then using
22
 * the callback to initialise it to an empty STACK.
23
 *
24
 * This means that the field will be correctly encoded unless
25
 * we NULL out the field.
26
 *
27
 * As a result we no longer need the req_kludge field because
28
 * the information is now contained in the attributes field:
29
 * 1. If it is NULL then it's the invalid omission.
30
 * 2. If it is empty it is the correct encoding.
31
 * 3. If it is not empty then some attributes are present.
32
 *
33
 */
34
35
static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
36
    void *exarg)
37
0
{
38
0
    X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
39
40
0
    if (operation == ASN1_OP_NEW_POST) {
41
0
        rinf->attributes = sk_X509_ATTRIBUTE_new_null();
42
0
        if (!rinf->attributes)
43
0
            return 0;
44
0
    }
45
0
    return 1;
46
0
}
47
48
static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
49
    void *exarg)
50
0
{
51
0
    X509_REQ *ret = (X509_REQ *)*pval;
52
53
0
    switch (operation) {
54
0
    case ASN1_OP_D2I_PRE:
55
0
        ASN1_OCTET_STRING_free(ret->distinguishing_id);
56
        /* fall through */
57
0
    case ASN1_OP_NEW_POST:
58
0
        ret->distinguishing_id = NULL;
59
0
        break;
60
61
0
    case ASN1_OP_FREE_POST:
62
0
        ASN1_OCTET_STRING_free(ret->distinguishing_id);
63
0
        break;
64
0
    case ASN1_OP_DUP_POST: {
65
0
        X509_REQ *old = exarg;
66
67
0
        if (old->req_info.pubkey != NULL) {
68
0
            EVP_PKEY *pkey = X509_PUBKEY_get0(old->req_info.pubkey);
69
70
0
            if (pkey != NULL) {
71
0
                pkey = EVP_PKEY_dup(pkey);
72
0
                if (pkey == NULL) {
73
0
                    ERR_raise(ERR_LIB_X509, ERR_R_EVP_LIB);
74
0
                    return 0;
75
0
                }
76
0
                if (!X509_PUBKEY_set(&ret->req_info.pubkey, pkey)) {
77
0
                    EVP_PKEY_free(pkey);
78
0
                    ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
79
0
                    return 0;
80
0
                }
81
0
                EVP_PKEY_free(pkey);
82
0
            }
83
0
        }
84
0
    } break;
85
0
    case ASN1_OP_GET0_LIBCTX:
86
0
        ossl_x509_req_get0_libctx(ret, exarg, NULL);
87
0
        break;
88
0
    case ASN1_OP_GET0_PROPQ:
89
0
        ossl_x509_req_get0_libctx(ret, NULL, exarg);
90
0
        break;
91
0
    }
92
93
0
    return 1;
94
0
}
95
96
ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
97
    ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
98
    ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
99
    ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
100
    /* This isn't really OPTIONAL but it gets round invalid
101
     * encodings
102
     */
103
    ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
104
} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
105
106
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
107
108
ASN1_SEQUENCE_ref(X509_REQ, req_cb) = {
109
    ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO),
110
    ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR),
111
    ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
112
} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
113
114
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
115
116
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
117
118
void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *d_id)
119
0
{
120
0
    ASN1_OCTET_STRING_free(x->distinguishing_id);
121
0
    x->distinguishing_id = d_id;
122
0
}
123
124
ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x)
125
0
{
126
0
    return x->distinguishing_id;
127
0
}
128
129
void ossl_x509_req_get0_libctx(const X509_REQ *x, OSSL_LIB_CTX **libctx,
130
    const char **propq)
131
0
{
132
0
    if (libctx != NULL)
133
0
        *libctx = NULL;
134
0
    if (propq != NULL)
135
0
        *propq = NULL;
136
0
    if (x->req_info.pubkey != NULL)
137
0
        (void)ossl_x509_PUBKEY_get0_libctx(libctx, propq, x->req_info.pubkey);
138
0
}
139
140
X509_REQ *X509_REQ_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
141
0
{
142
0
    return (X509_REQ *)ASN1_item_new_ex(ASN1_ITEM_rptr(X509_REQ), libctx, propq);
143
0
}