2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 print_int_text(const char *name
, const unsigned char *buf
, size_t len
)
39 printf("%s = ", name
);
40 for (u
= 0; u
< len
; u
++) {
41 printf("%02X", buf
[u
]);
47 print_int_C(const char *name
, const unsigned char *buf
, size_t len
)
51 printf("\nstatic const unsigned char %s[] = {", name
);
52 for (u
= 0; u
< len
; u
++) {
61 printf("0x%02X", buf
[u
]);
67 print_rsa(const br_rsa_private_key
*sk
, int print_text
, int print_C
)
70 print_int_text("p ", sk
->p
, sk
->plen
);
71 print_int_text("q ", sk
->q
, sk
->qlen
);
72 print_int_text("dp", sk
->dp
, sk
->dplen
);
73 print_int_text("dq", sk
->dq
, sk
->dqlen
);
74 print_int_text("iq", sk
->iq
, sk
->iqlen
);
77 print_int_C("RSA_P", sk
->p
, sk
->plen
);
78 print_int_C("RSA_Q", sk
->q
, sk
->qlen
);
79 print_int_C("RSA_DP", sk
->dp
, sk
->dplen
);
80 print_int_C("RSA_DQ", sk
->dq
, sk
->dqlen
);
81 print_int_C("RSA_IQ", sk
->iq
, sk
->iqlen
);
82 printf("\nstatic const br_rsa_private_key RSA = {\n");
83 printf("\t%lu,\n", (unsigned long)sk
->n_bitlen
);
84 printf("\t(unsigned char *)RSA_P, sizeof RSA_P,\n");
85 printf("\t(unsigned char *)RSA_Q, sizeof RSA_Q,\n");
86 printf("\t(unsigned char *)RSA_DP, sizeof RSA_DP,\n");
87 printf("\t(unsigned char *)RSA_DQ, sizeof RSA_DQ,\n");
88 printf("\t(unsigned char *)RSA_IQ, sizeof RSA_IQ\n");
94 print_ec(const br_ec_private_key
*sk
, int print_text
, int print_C
)
97 print_int_text("x", sk
->x
, sk
->xlen
);
100 print_int_C("EC_X", sk
->x
, sk
->xlen
);
101 printf("\nstatic const br_ec_private_key EC = {\n");
102 printf("\t%d,\n", sk
->curve
);
103 printf("\t(unsigned char *)EC_X, sizeof EC_X\n");
109 parse_rsa_spec(const char *kgen_spec
, unsigned *size
, uint32_t *pubexp
)
116 if (*p
!= 'r' && *p
!= 'R') {
120 if (*p
!= 's' && *p
!= 'S') {
124 if (*p
!= 'a' && *p
!= 'A') {
132 } else if (*p
!= ':') {
136 ul
= strtoul(p
, &end
, 10);
137 if (ul
< 512 || ul
> 32768) {
145 } else if (*p
!= ':') {
149 ul
= strtoul(p
, &end
, 10);
150 if ((ul
& 1) == 0 || ul
== 1 || ((ul
>> 30) >> 2) != 0) {
161 keygen_rsa(unsigned size
, uint32_t pubexp
, int print_text
, int print_C
)
163 br_hmac_drbg_context rng
;
164 br_prng_seeder seeder
;
166 br_rsa_private_key sk
;
167 unsigned char *kbuf_priv
;
170 seeder
= br_prng_seeder_system(NULL
);
172 fprintf(stderr
, "ERROR: no system source of randomness\n");
175 br_hmac_drbg_init(&rng
, &br_sha256_vtable
, NULL
, 0);
176 if (!seeder(&rng
.vtable
)) {
177 fprintf(stderr
, "ERROR: system source of randomness failed\n");
180 kbuf_priv
= xmalloc(BR_RSA_KBUF_PRIV_SIZE(size
));
181 kg
= br_rsa_keygen_get_default();
182 r
= kg(&rng
.vtable
, &sk
, kbuf_priv
, NULL
, NULL
, size
, pubexp
);
184 fprintf(stderr
, "ERROR: RSA key pair generation failed\n");
186 print_rsa(&sk
, print_text
, print_C
);
193 decode_key(const unsigned char *buf
, size_t len
, int print_text
, int print_C
)
195 br_skey_decoder_context dc
;
198 br_skey_decoder_init(&dc
);
199 br_skey_decoder_push(&dc
, buf
, len
);
200 err
= br_skey_decoder_last_error(&dc
);
202 const char *errname
, *errmsg
;
204 fprintf(stderr
, "ERROR (decoding): err=%d\n", err
);
205 errname
= find_error_name(err
, &errmsg
);
206 if (errname
!= NULL
) {
207 fprintf(stderr
, " %s: %s\n", errname
, errmsg
);
209 fprintf(stderr
, " (unknown)\n");
213 switch (br_skey_decoder_key_type(&dc
)) {
214 const br_rsa_private_key
*rk
;
215 const br_ec_private_key
*ek
;
218 rk
= br_skey_decoder_get_rsa(&dc
);
219 printf("RSA key (%lu bits)\n", (unsigned long)rk
->n_bitlen
);
220 print_rsa(rk
, print_text
, print_C
);
224 ek
= br_skey_decoder_get_ec(&dc
);
225 printf("EC key (curve = %d: %s)\n",
226 ek
->curve
, ec_curve_name(ek
->curve
));
227 print_ec(ek
, print_text
, print_C
);
231 fprintf(stderr
, "Unknown key type: %d\n",
232 br_skey_decoder_key_type(&dc
));
243 "usage: brssl skey [ options ] file...\n");
247 " -q suppress verbose messages\n");
249 " -text print public key details (human-readable)\n");
251 " -C print public key details (C code)\n");
253 " -gen spec generate a new key using the provided key specification\n");
255 "Key specification begins with a key type, followed by optional parameters\n");
257 "that depend on the key type, separated by colon characters:\n");
259 " rsa[:size[:pubexep]] RSA key (defaults: size = 2048, pubexp = 3)\n");
264 do_skey(int argc
, char *argv
[])
269 int print_text
, print_C
;
273 const char *kgen_spec
;
283 for (i
= 0; i
< argc
; i
++) {
292 if (eqstr(arg
, "-v") || eqstr(arg
, "-verbose")) {
294 } else if (eqstr(arg
, "-q") || eqstr(arg
, "-quiet")) {
296 } else if (eqstr(arg
, "-text")) {
298 } else if (eqstr(arg
, "-C")) {
300 } else if (eqstr(arg
, "-gen")) {
303 "ERROR: no argument for '-gen'\n");
305 goto skey_exit_error
;
307 if (kgen_spec
!= NULL
) {
309 "ERROR: multiple '-gen' options\n");
311 goto skey_exit_error
;
316 fprintf(stderr
, "ERROR: unknown option: '%s'\n", arg
);
318 goto skey_exit_error
;
321 if (kgen_spec
!= NULL
) {
325 if (num_files
!= 0) {
327 "ERROR: key files provided while generating\n");
329 goto skey_exit_error
;
332 if (parse_rsa_spec(kgen_spec
, &rsa_size
, &rsa_pubexp
)) {
333 keygen_rsa(rsa_size
, rsa_pubexp
, print_text
, print_C
);
336 "ERROR: unknown key specification: '%s'\n",
339 goto skey_exit_error
;
341 } else if (num_files
== 0) {
342 fprintf(stderr
, "ERROR: no private key provided\n");
344 goto skey_exit_error
;
347 for (i
= 0; i
< argc
; i
++) {
354 buf
= read_file(fname
, &len
);
356 goto skey_exit_error
;
358 if (looks_like_DER(buf
, len
)) {
360 fprintf(stderr
, "File '%s': ASN.1/DER object\n",
363 if (decode_key(buf
, len
, print_text
, print_C
) < 0) {
364 goto skey_exit_error
;
370 fprintf(stderr
, "File '%s': decoding as PEM\n",
373 pos
= decode_pem(buf
, len
, &num
);
375 goto skey_exit_error
;
377 for (u
= 0; pos
[u
].name
; u
++) {
381 if (eqstr(name
, "RSA PRIVATE KEY")
382 || eqstr(name
, "EC PRIVATE KEY")
383 || eqstr(name
, "PRIVATE KEY"))
385 if (decode_key(pos
[u
].data
,
387 print_text
, print_C
) < 0)
389 goto skey_exit_error
;
399 for (u
= 0; pos
[u
].name
; u
++) {
400 free_pem_object_contents(&pos
[u
]);
410 * Release allocated structures.
417 for (u
= 0; pos
[u
].name
; u
++) {
418 free_pem_object_contents(&pos
[u
]);