Coverage Report

Created: 2026-06-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/x509/v3_akey.cc
Line
Count
Source
1
// Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <stdio.h>
16
#include <string.h>
17
18
#include <openssl/asn1.h>
19
#include <openssl/asn1t.h>
20
#include <openssl/conf.h>
21
#include <openssl/err.h>
22
#include <openssl/mem.h>
23
#include <openssl/obj.h>
24
#include <openssl/x509.h>
25
26
#include "internal.h"
27
28
29
using namespace bssl;
30
31
static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(
32
    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist);
33
static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method,
34
                                 const X509V3_CTX *ctx,
35
                                 const STACK_OF(CONF_VALUE) *values);
36
37
const X509V3_EXT_METHOD bssl::v3_akey_id = {
38
    NID_authority_key_identifier,
39
    X509V3_EXT_MULTILINE,
40
    ASN1_ITEM_ref(AUTHORITY_KEYID),
41
    nullptr,
42
    nullptr,
43
    nullptr,
44
    nullptr,
45
    nullptr,
46
    nullptr,
47
    i2v_AUTHORITY_KEYID,
48
    v2i_AUTHORITY_KEYID,
49
    nullptr,
50
    nullptr,
51
    nullptr,
52
};
53
54
static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(
55
306
    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) {
56
306
  const AUTHORITY_KEYID *akeyid =
57
306
      reinterpret_cast<const AUTHORITY_KEYID *>(ext);
58
306
  int extlist_was_null = extlist == nullptr;
59
306
  if (akeyid->keyid) {
60
195
    char *tmp = x509v3_bytes_to_hex(akeyid->keyid->data, akeyid->keyid->length);
61
195
    int ok = tmp != nullptr && X509V3_add_value("keyid", tmp, &extlist);
62
195
    OPENSSL_free(tmp);
63
195
    if (!ok) {
64
0
      goto err;
65
0
    }
66
195
  }
67
306
  if (akeyid->issuer) {
68
75
    STACK_OF(CONF_VALUE) *tmpextlist =
69
75
        i2v_GENERAL_NAMES(nullptr, akeyid->issuer, extlist);
70
75
    if (tmpextlist == nullptr) {
71
12
      goto err;
72
12
    }
73
63
    extlist = tmpextlist;
74
63
  }
75
294
  if (akeyid->serial) {
76
116
    if (!X509V3_add_value_int("serial", akeyid->serial, &extlist)) {
77
0
      goto err;
78
0
    }
79
116
  }
80
294
  return extlist;
81
82
12
err:
83
12
  if (extlist_was_null) {
84
12
    sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free);
85
12
  }
86
12
  return nullptr;
87
294
}
88
89
// Currently two options:
90
//
91
// - keyid: Use the issuer's subject key ID. The value 'always' means it's an
92
//   error if the issuer certificate doesn't have one.
93
//
94
// - issuer: Use the issuer's issuer and serial number. The default is to only
95
//   use this if the key ID is not present. The value 'always' means it's always
96
//   included.
97
static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method,
98
                                 const X509V3_CTX *ctx,
99
0
                                 const STACK_OF(CONF_VALUE) *values) {
100
0
  enum Option { kOff = 0, kOn = 1, kAlways = 2 };
101
0
  Option use_key_id = kOff, use_issuer = kOff;
102
0
  for (const CONF_VALUE *cnf : values) {
103
0
    if (!strcmp(cnf->name, "keyid")) {
104
0
      use_key_id = kOn;
105
0
      if (cnf->value && !strcmp(cnf->value, "always")) {
106
0
        use_key_id = kAlways;
107
0
      }
108
0
    } else if (!strcmp(cnf->name, "issuer")) {
109
0
      use_issuer = kOn;
110
0
      if (cnf->value && !strcmp(cnf->value, "always")) {
111
0
        use_issuer = kAlways;
112
0
      }
113
0
    } else {
114
0
      OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION);
115
0
      ERR_add_error_data(2, "name=", cnf->name);
116
0
      return nullptr;
117
0
    }
118
0
  }
119
120
0
  if (!ctx || !ctx->issuer_cert) {
121
0
    if (ctx && (ctx->flags == X509V3_CTX_TEST)) {
122
0
      return AUTHORITY_KEYID_new();
123
0
    }
124
0
    OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
125
0
    return nullptr;
126
0
  }
127
128
0
  UniquePtr<ASN1_OCTET_STRING> key_id;
129
0
  if (use_key_id != kOff) {
130
0
    int critical;
131
0
    key_id.reset(static_cast<ASN1_OCTET_STRING *>(X509_get_ext_d2i(
132
0
        ctx->issuer_cert, NID_subject_key_identifier, &critical, nullptr)));
133
0
    if (key_id == nullptr && critical != -1) {
134
0
      return nullptr;  // Syntax error in the extension.
135
0
    }
136
0
    if (use_key_id == kAlways && key_id == nullptr) {
137
0
      OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
138
0
      return nullptr;
139
0
    }
140
0
  }
141
142
0
  UniquePtr<ASN1_INTEGER> serial;
143
0
  UniquePtr<GENERAL_NAMES> issuer_gens;
144
0
  if ((use_issuer == kOn && key_id == nullptr) || use_issuer == kAlways) {
145
0
    UniquePtr<X509_NAME> issuer_name(
146
0
        X509_NAME_dup(X509_get_issuer_name(ctx->issuer_cert)));
147
0
    serial.reset(ASN1_INTEGER_dup(X509_get0_serialNumber(ctx->issuer_cert)));
148
0
    if (issuer_name == nullptr || serial == nullptr) {
149
0
      OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
150
0
      return nullptr;
151
0
    }
152
    // AKID wraps the issuer name in a GeneralNames structure.
153
0
    UniquePtr<GENERAL_NAME> gen(GENERAL_NAME_new());
154
0
    if (gen == nullptr) {
155
0
      return nullptr;
156
0
    }
157
0
    gen->type = GEN_DIRNAME;
158
0
    gen->d.directoryName = issuer_name.release();
159
0
    issuer_gens.reset(sk_GENERAL_NAME_new_null());
160
0
    if (issuer_gens == nullptr ||
161
0
        !PushToStack(issuer_gens.get(), std::move(gen))) {
162
0
      return nullptr;
163
0
    }
164
0
  }
165
166
0
  UniquePtr<AUTHORITY_KEYID> akid(AUTHORITY_KEYID_new());
167
0
  if (akid == nullptr) {
168
0
    return nullptr;
169
0
  }
170
0
  akid->issuer = issuer_gens.release();
171
0
  akid->serial = serial.release();
172
0
  akid->keyid = key_id.release();
173
0
  return akid.release();
174
0
}