Coverage Report

Created: 2026-10-27 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/evp/print.cc
Line
Count
Source
1
// Copyright 2006-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/evp.h>
16
17
#include <openssl/bio.h>
18
#include <openssl/bn.h>
19
#include <openssl/dsa.h>
20
#include <openssl/ec.h>
21
#include <openssl/ec_key.h>
22
#include <openssl/mem.h>
23
#include <openssl/rsa.h>
24
25
#include "../internal.h"
26
27
28
using namespace bssl;
29
30
2.32k
static int print_hex(BIO *bp, const uint8_t *data, size_t len, int off) {
31
183k
  for (size_t i = 0; i < len; i++) {
32
181k
    if ((i % 15) == 0) {
33
12.9k
      if (BIO_puts(bp, "\n") <= 0 ||  //
34
12.9k
          !BIO_indent(bp, off + 4, 128)) {
35
0
        return 0;
36
0
      }
37
12.9k
    }
38
181k
    if (BIO_printf(bp, "%02x%s", data[i], (i + 1 == len) ? "" : ":") <= 0) {
39
0
      return 0;
40
0
    }
41
181k
  }
42
2.32k
  if (BIO_write(bp, "\n", 1) <= 0) {
43
0
    return 0;
44
0
  }
45
2.32k
  return 1;
46
2.32k
}
47
48
1.63k
static int bn_print(BIO *bp, const char *name, const BIGNUM *num, int off) {
49
1.63k
  if (num == nullptr) {
50
0
    return 1;
51
0
  }
52
53
1.63k
  if (!BIO_indent(bp, off, 128)) {
54
0
    return 0;
55
0
  }
56
1.63k
  if (BN_is_zero(num)) {
57
0
    if (BIO_printf(bp, "%s 0\n", name) <= 0) {
58
0
      return 0;
59
0
    }
60
0
    return 1;
61
0
  }
62
63
1.63k
  uint64_t u64;
64
1.63k
  if (BN_get_u64(num, &u64)) {
65
856
    const char *neg = BN_is_negative(num) ? "-" : "";
66
856
    return BIO_printf(bp, "%s %s%" PRIu64 " (%s0x%" PRIx64 ")\n", name, neg,
67
856
                      u64, neg, u64) > 0;
68
856
  }
69
70
783
  if (BIO_printf(bp, "%s%s", name,
71
783
                 (BN_is_negative(num)) ? " (Negative)" : "") <= 0) {
72
0
    return 0;
73
0
  }
74
75
  // Print `num` in hex, adding a leading zero, as in ASN.1, if the high bit
76
  // is set.
77
  //
78
  // TODO(davidben): Do we need to do this? We already print "(Negative)" above
79
  // and negative values are never valid in keys anyway.
80
783
  size_t len = BN_num_bytes(num);
81
783
  uint8_t *buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len + 1));
82
783
  if (buf == nullptr) {
83
0
    return 0;
84
0
  }
85
86
783
  buf[0] = 0;
87
783
  BN_bn2bin(num, buf + 1);
88
783
  int ret;
89
783
  if (len > 0 && (buf[1] & 0x80) != 0) {
90
    // Print the whole buffer.
91
608
    ret = print_hex(bp, buf, len + 1, off);
92
608
  } else {
93
    // Skip the leading zero.
94
175
    ret = print_hex(bp, buf + 1, len, off);
95
175
  }
96
783
  OPENSSL_free(buf);
97
783
  return ret;
98
783
}
99
100
// RSA keys.
101
102
static int do_rsa_print(BIO *out, const RSA *rsa, int off,
103
545
                        int include_private) {
104
545
  int mod_len = 0;
105
545
  if (RSA_get0_n(rsa) != nullptr) {
106
545
    mod_len = RSA_bits(rsa);
107
545
  }
108
109
545
  if (!BIO_indent(out, off, 128)) {
110
0
    return 0;
111
0
  }
112
113
545
  const char *s, *str;
114
545
  if (include_private && RSA_get0_d(rsa) != nullptr) {
115
2
    if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
116
0
      return 0;
117
0
    }
118
2
    str = "modulus:";
119
2
    s = "publicExponent:";
120
543
  } else {
121
543
    if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
122
0
      return 0;
123
0
    }
124
543
    str = "Modulus:";
125
543
    s = "Exponent:";
126
543
  }
127
545
  if (!bn_print(out, str, RSA_get0_n(rsa), off) ||
128
545
      !bn_print(out, s, RSA_get0_e(rsa), off)) {
129
0
    return 0;
130
0
  }
131
132
545
  if (include_private) {
133
2
    if (!bn_print(out, "privateExponent:", RSA_get0_d(rsa), off) ||
134
2
        !bn_print(out, "prime1:", RSA_get0_p(rsa), off) ||
135
2
        !bn_print(out, "prime2:", RSA_get0_q(rsa), off) ||
136
2
        !bn_print(out, "exponent1:", RSA_get0_dmp1(rsa), off) ||
137
2
        !bn_print(out, "exponent2:", RSA_get0_dmq1(rsa), off) ||
138
2
        !bn_print(out, "coefficient:", RSA_get0_iqmp(rsa), off)) {
139
0
      return 0;
140
0
    }
141
2
  }
142
143
545
  return 1;
144
545
}
145
146
543
static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
147
543
  return do_rsa_print(bp, EVP_PKEY_get0_RSA(pkey), indent, 0);
148
543
}
149
150
2
static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
151
2
  return do_rsa_print(bp, EVP_PKEY_get0_RSA(pkey), indent, 1);
152
2
}
153
154
155
// EC keys.
156
157
2.47k
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
158
2.47k
  const EC_GROUP *group;
159
2.47k
  if (x == nullptr || (group = EC_KEY_get0_group(x)) == nullptr) {
160
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_PASSED_NULL_PARAMETER);
161
0
    return 0;
162
0
  }
163
164
2.47k
  const char *ecstr;
165
2.47k
  if (ktype == 2) {
166
537
    ecstr = "Private-Key";
167
1.93k
  } else if (ktype == 1) {
168
1.00k
    ecstr = "Public-Key";
169
1.00k
  } else {
170
934
    ecstr = "ECDSA-Parameters";
171
934
  }
172
173
2.47k
  if (!BIO_indent(bp, off, 128)) {
174
0
    return 0;
175
0
  }
176
2.47k
  int curve_name = EC_GROUP_get_curve_name(group);
177
2.47k
  if (BIO_printf(bp, "%s: (%s)\n", ecstr,
178
2.47k
                 curve_name == NID_undef
179
2.47k
                     ? "unknown curve"
180
2.47k
                     : EC_curve_nid2nist(curve_name)) <= 0) {
181
0
    return 0;
182
0
  }
183
184
2.47k
  if (ktype == 2) {
185
537
    const BIGNUM *priv_key = EC_KEY_get0_private_key(x);
186
537
    if (priv_key != nullptr &&  //
187
537
        !bn_print(bp, "priv:", priv_key, off)) {
188
0
      return 0;
189
0
    }
190
537
  }
191
192
2.47k
  if (ktype > 0 && EC_KEY_get0_public_key(x) != nullptr) {
193
1.54k
    uint8_t *pub = nullptr;
194
1.54k
    size_t pub_len = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, nullptr);
195
1.54k
    if (pub_len == 0) {
196
0
      return 0;
197
0
    }
198
1.54k
    int ret = BIO_indent(bp, off, 128) &&  //
199
1.54k
              BIO_puts(bp, "pub:") > 0 &&  //
200
1.54k
              print_hex(bp, pub, pub_len, off);
201
1.54k
    OPENSSL_free(pub);
202
1.54k
    if (!ret) {
203
0
      return 0;
204
0
    }
205
1.54k
  }
206
207
2.47k
  return 1;
208
2.47k
}
209
210
934
static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
211
934
  return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 0);
212
934
}
213
214
1.00k
static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
215
1.00k
  return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 1);
216
1.00k
}
217
218
219
537
static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
220
537
  return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 2);
221
537
}
222
223
224
typedef struct {
225
  int type;
226
  int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent);
227
  int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent);
228
  int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent);
229
} EVP_PKEY_PRINT_METHOD;
230
231
static const EVP_PKEY_PRINT_METHOD kPrintMethods[] = {
232
    {
233
        EVP_PKEY_RSA,
234
        rsa_pub_print,
235
        rsa_priv_print,
236
        /*param_print=*/nullptr,
237
    },
238
    {
239
        EVP_PKEY_EC,
240
        eckey_pub_print,
241
        eckey_priv_print,
242
        eckey_param_print,
243
    },
244
};
245
246
5.83k
static const EVP_PKEY_PRINT_METHOD *find_method(int type) {
247
10.9k
  for (const auto &p : kPrintMethods) {
248
10.9k
    if (p.type == type) {
249
3.23k
      return &p;
250
3.23k
    }
251
10.9k
  }
252
2.60k
  return nullptr;
253
5.83k
}
254
255
static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
256
2.81k
                             const char *kstr) {
257
2.81k
  BIO_indent(out, indent, 128);
258
2.81k
  BIO_printf(out, "%s algorithm unsupported\n", kstr);
259
2.81k
  return 1;
260
2.81k
}
261
262
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
263
2.46k
                          ASN1_PCTX *pctx) {
264
2.46k
  const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
265
2.46k
  if (method != nullptr && method->pub_print != nullptr) {
266
1.54k
    return method->pub_print(out, pkey, indent);
267
1.54k
  }
268
922
  return print_unsupported(out, pkey, indent, "Public Key");
269
2.46k
}
270
271
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
272
1.30k
                           ASN1_PCTX *pctx) {
273
1.30k
  const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
274
1.30k
  if (method != nullptr && method->priv_print != nullptr) {
275
539
    return method->priv_print(out, pkey, indent);
276
539
  }
277
761
  return print_unsupported(out, pkey, indent, "Private Key");
278
1.30k
}
279
280
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
281
2.06k
                          ASN1_PCTX *pctx) {
282
2.06k
  const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
283
2.06k
  if (method != nullptr && method->param_print != nullptr) {
284
934
    return method->param_print(out, pkey, indent);
285
934
  }
286
1.13k
  return print_unsupported(out, pkey, indent, "Parameters");
287
2.06k
}