Coverage Report

Created: 2026-05-11 06:45

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.64k
static int print_hex(BIO *bp, const uint8_t *data, size_t len, int off) {
31
203k
  for (size_t i = 0; i < len; i++) {
32
200k
    if ((i % 15) == 0) {
33
14.3k
      if (BIO_puts(bp, "\n") <= 0 ||  //
34
14.3k
          !BIO_indent(bp, off + 4, 128)) {
35
0
        return 0;
36
0
      }
37
14.3k
    }
38
200k
    if (BIO_printf(bp, "%02x%s", data[i], (i + 1 == len) ? "" : ":") <= 0) {
39
0
      return 0;
40
0
    }
41
200k
  }
42
2.64k
  if (BIO_write(bp, "\n", 1) <= 0) {
43
0
    return 0;
44
0
  }
45
2.64k
  return 1;
46
2.64k
}
47
48
1.58k
static int bn_print(BIO *bp, const char *name, const BIGNUM *num, int off) {
49
1.58k
  if (num == nullptr) {
50
0
    return 1;
51
0
  }
52
53
1.58k
  if (!BIO_indent(bp, off, 128)) {
54
0
    return 0;
55
0
  }
56
1.58k
  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.58k
  uint64_t u64;
64
1.58k
  if (BN_get_u64(num, &u64)) {
65
811
    const char *neg = BN_is_negative(num) ? "-" : "";
66
811
    return BIO_printf(bp, "%s %s%" PRIu64 " (%s0x%" PRIx64 ")\n", name, neg,
67
811
                      u64, neg, u64) > 0;
68
811
  }
69
70
769
  if (BIO_printf(bp, "%s%s", name,
71
769
                 (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
769
  size_t len = BN_num_bytes(num);
81
769
  uint8_t *buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len + 1));
82
769
  if (buf == nullptr) {
83
0
    return 0;
84
0
  }
85
86
769
  buf[0] = 0;
87
769
  BN_bn2bin(num, buf + 1);
88
769
  int ret;
89
769
  if (len > 0 && (buf[1] & 0x80) != 0) {
90
    // Print the whole buffer.
91
592
    ret = print_hex(bp, buf, len + 1, off);
92
592
  } else {
93
    // Skip the leading zero.
94
177
    ret = print_hex(bp, buf + 1, len, off);
95
177
  }
96
769
  OPENSSL_free(buf);
97
769
  return ret;
98
769
}
99
100
// RSA keys.
101
102
static int do_rsa_print(BIO *out, const RSA *rsa, int off,
103
526
                        int include_private) {
104
526
  int mod_len = 0;
105
526
  if (RSA_get0_n(rsa) != nullptr) {
106
526
    mod_len = RSA_bits(rsa);
107
526
  }
108
109
526
  if (!BIO_indent(out, off, 128)) {
110
0
    return 0;
111
0
  }
112
113
526
  const char *s, *str;
114
526
  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
524
  } else {
121
524
    if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
122
0
      return 0;
123
0
    }
124
524
    str = "Modulus:";
125
524
    s = "Exponent:";
126
524
  }
127
526
  if (!bn_print(out, str, RSA_get0_n(rsa), off) ||
128
526
      !bn_print(out, s, RSA_get0_e(rsa), off)) {
129
0
    return 0;
130
0
  }
131
132
526
  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
526
  return 1;
144
526
}
145
146
524
static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
147
524
  return do_rsa_print(bp, EVP_PKEY_get0_RSA(pkey), indent, 0);
148
524
}
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.97k
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
158
2.97k
  const EC_GROUP *group;
159
2.97k
  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.97k
  const char *ecstr;
165
2.97k
  if (ktype == 2) {
166
516
    ecstr = "Private-Key";
167
2.46k
  } else if (ktype == 1) {
168
1.36k
    ecstr = "Public-Key";
169
1.36k
  } else {
170
1.09k
    ecstr = "ECDSA-Parameters";
171
1.09k
  }
172
173
2.97k
  if (!BIO_indent(bp, off, 128)) {
174
0
    return 0;
175
0
  }
176
2.97k
  int curve_name = EC_GROUP_get_curve_name(group);
177
2.97k
  if (BIO_printf(bp, "%s: (%s)\n", ecstr,
178
2.97k
                 curve_name == NID_undef
179
2.97k
                     ? "unknown curve"
180
2.97k
                     : EC_curve_nid2nist(curve_name)) <= 0) {
181
0
    return 0;
182
0
  }
183
184
2.97k
  if (ktype == 2) {
185
516
    const BIGNUM *priv_key = EC_KEY_get0_private_key(x);
186
516
    if (priv_key != nullptr &&  //
187
516
        !bn_print(bp, "priv:", priv_key, off)) {
188
0
      return 0;
189
0
    }
190
516
  }
191
192
2.97k
  if (ktype > 0 && EC_KEY_get0_public_key(x) != nullptr) {
193
1.87k
    uint8_t *pub = nullptr;
194
1.87k
    size_t pub_len = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, nullptr);
195
1.87k
    if (pub_len == 0) {
196
0
      return 0;
197
0
    }
198
1.87k
    int ret = BIO_indent(bp, off, 128) &&  //
199
1.87k
              BIO_puts(bp, "pub:") > 0 &&  //
200
1.87k
              print_hex(bp, pub, pub_len, off);
201
1.87k
    OPENSSL_free(pub);
202
1.87k
    if (!ret) {
203
0
      return 0;
204
0
    }
205
1.87k
  }
206
207
2.97k
  return 1;
208
2.97k
}
209
210
1.09k
static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
211
1.09k
  return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 0);
212
1.09k
}
213
214
1.36k
static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
215
1.36k
  return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 1);
216
1.36k
}
217
218
219
516
static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
220
516
  return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 2);
221
516
}
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.55k
static const EVP_PKEY_PRINT_METHOD *find_method(int type) {
247
10.3k
  for (const auto &p : kPrintMethods) {
248
10.3k
    if (p.type == type) {
249
3.72k
      return &p;
250
3.72k
    }
251
10.3k
  }
252
1.83k
  return nullptr;
253
5.55k
}
254
255
static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
256
2.05k
                             const char *kstr) {
257
2.05k
  BIO_indent(out, indent, 128);
258
2.05k
  BIO_printf(out, "%s algorithm unsupported\n", kstr);
259
2.05k
  return 1;
260
2.05k
}
261
262
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
263
2.50k
                          ASN1_PCTX *pctx) {
264
2.50k
  const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
265
2.50k
  if (method != nullptr && method->pub_print != nullptr) {
266
1.88k
    return method->pub_print(out, pkey, indent);
267
1.88k
  }
268
621
  return print_unsupported(out, pkey, indent, "Public Key");
269
2.50k
}
270
271
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
272
1.11k
                           ASN1_PCTX *pctx) {
273
1.11k
  const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
274
1.11k
  if (method != nullptr && method->priv_print != nullptr) {
275
518
    return method->priv_print(out, pkey, indent);
276
518
  }
277
596
  return print_unsupported(out, pkey, indent, "Private Key");
278
1.11k
}
279
280
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
281
1.93k
                          ASN1_PCTX *pctx) {
282
1.93k
  const EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
283
1.93k
  if (method != nullptr && method->param_print != nullptr) {
284
1.09k
    return method->param_print(out, pkey, indent);
285
1.09k
  }
286
838
  return print_unsupported(out, pkey, indent, "Parameters");
287
1.93k
}