Coverage Report

Created: 2025-06-24 07:00

/src/boringssl/crypto/x509/x_pubkey.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 1995-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 <openssl/x509.h>
16
17
#include <limits.h>
18
19
#include <openssl/asn1.h>
20
#include <openssl/asn1t.h>
21
#include <openssl/bytestring.h>
22
#include <openssl/err.h>
23
#include <openssl/evp.h>
24
#include <openssl/mem.h>
25
#include <openssl/obj.h>
26
27
#include "../internal.h"
28
#include "internal.h"
29
30
31
202k
static void x509_pubkey_changed(X509_PUBKEY *pub) {
32
202k
  EVP_PKEY_free(pub->pkey);
33
202k
  pub->pkey = NULL;
34
35
  // Re-encode the |X509_PUBKEY| to DER and parse it with EVP's APIs.
36
202k
  uint8_t *spki = NULL;
37
202k
  int spki_len = i2d_X509_PUBKEY(pub, &spki);
38
202k
  EVP_PKEY *pkey;
39
202k
  if (spki_len < 0) {
40
0
    goto err;
41
0
  }
42
43
202k
  CBS cbs;
44
202k
  CBS_init(&cbs, spki, (size_t)spki_len);
45
202k
  pkey = EVP_parse_public_key(&cbs);
46
202k
  if (pkey == NULL || CBS_len(&cbs) != 0) {
47
99.9k
    EVP_PKEY_free(pkey);
48
99.9k
    goto err;
49
99.9k
  }
50
51
102k
  pub->pkey = pkey;
52
53
202k
err:
54
202k
  OPENSSL_free(spki);
55
  // If the operation failed, clear errors. An |X509_PUBKEY| whose key we cannot
56
  // parse is still a valid SPKI. It just cannot be converted to an |EVP_PKEY|.
57
202k
  ERR_clear_error();
58
202k
}
59
60
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
61
1.35M
                     void *exarg) {
62
1.35M
  X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
63
1.35M
  if (operation == ASN1_OP_FREE_POST) {
64
236k
    EVP_PKEY_free(pubkey->pkey);
65
1.11M
  } else if (operation == ASN1_OP_D2I_POST) {
66
202k
    x509_pubkey_changed(pubkey);
67
202k
  }
68
1.35M
  return 1;
69
1.35M
}
70
71
ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
72
    ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
73
    ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING),
74
} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
75
76
IMPLEMENT_ASN1_FUNCTIONS_const(X509_PUBKEY)
77
78
0
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) {
79
0
  X509_PUBKEY *pk = NULL;
80
0
  uint8_t *spki = NULL;
81
0
  size_t spki_len;
82
83
0
  if (x == NULL) {
84
0
    return 0;
85
0
  }
86
87
0
  CBB cbb;
88
0
  const uint8_t *p;
89
0
  if (!CBB_init(&cbb, 0) ||  //
90
0
      !EVP_marshal_public_key(&cbb, pkey) ||
91
0
      !CBB_finish(&cbb, &spki, &spki_len) ||  //
92
0
      spki_len > LONG_MAX) {
93
0
    CBB_cleanup(&cbb);
94
0
    OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
95
0
    goto error;
96
0
  }
97
98
0
  p = spki;
99
0
  pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len);
100
0
  if (pk == NULL || p != spki + spki_len) {
101
0
    OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
102
0
    goto error;
103
0
  }
104
105
0
  OPENSSL_free(spki);
106
0
  X509_PUBKEY_free(*x);
107
0
  *x = pk;
108
109
0
  return 1;
110
0
error:
111
0
  X509_PUBKEY_free(pk);
112
0
  OPENSSL_free(spki);
113
0
  return 0;
114
0
}
115
116
6.02k
EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key) {
117
6.02k
  if (key == NULL) {
118
0
    return NULL;
119
0
  }
120
121
6.02k
  if (key->pkey == NULL) {
122
4.86k
    OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
123
4.86k
    return NULL;
124
4.86k
  }
125
126
1.16k
  return key->pkey;
127
6.02k
}
128
129
3.21k
EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key) {
130
3.21k
  EVP_PKEY *pkey = X509_PUBKEY_get0(key);
131
3.21k
  if (pkey != NULL) {
132
622
    EVP_PKEY_up_ref(pkey);
133
622
  }
134
3.21k
  return pkey;
135
3.21k
}
136
137
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type,
138
0
                           void *param_value, uint8_t *key, int key_len) {
139
0
  if (!X509_ALGOR_set0(pub->algor, obj, param_type, param_value)) {
140
0
    return 0;
141
0
  }
142
143
0
  ASN1_STRING_set0(pub->public_key, key, key_len);
144
  // Set the number of unused bits to zero.
145
0
  pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
146
0
  pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
147
148
0
  x509_pubkey_changed(pub);
149
0
  return 1;
150
0
}
151
152
int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, const uint8_t **out_key,
153
                           int *out_key_len, X509_ALGOR **out_alg,
154
0
                           X509_PUBKEY *pub) {
155
0
  if (out_obj != NULL) {
156
0
    *out_obj = pub->algor->algorithm;
157
0
  }
158
0
  if (out_key != NULL) {
159
0
    *out_key = pub->public_key->data;
160
0
    *out_key_len = pub->public_key->length;
161
0
  }
162
0
  if (out_alg != NULL) {
163
0
    *out_alg = pub->algor;
164
0
  }
165
0
  return 1;
166
0
}
167
168
0
const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) {
169
0
  return pub->public_key;
170
0
}