1 /* vi: set sw=4 ts=4:
2 *
3 * Copyright (C) 2001 - 2020 Christian Hohnstaedt.
4 *
5 * All rights reserved.
6 */
7
8
9 #include "pki_evp.h"
10 #include "pass_info.h"
11 #include "func.h"
12 #include "db.h"
13 #include "entropy.h"
14 #include "BioByteArray.h"
15 #include "widgets/PwDialog.h"
16 #include "widgets/XcaWarning.h"
17 #include "widgets/XcaProgress.h"
18
19 #include <openssl/rand.h>
20 #include <openssl/evp.h>
21 #include <openssl/pem.h>
22 #include <openssl/pkcs12.h>
23 #include <openssl/err.h>
24
25 #include "openssl_compat.h"
26
27 Passwd pki_evp::passwd;
28 Passwd pki_evp::oldpasswd;
29
30 QString pki_evp::passHash = QString();
31
init()32 void pki_evp::init()
33 {
34 ownPass = ptCommon;
35 pkiType = asym_key;
36 }
37
setOwnPass(enum passType x)38 void pki_evp::setOwnPass(enum passType x)
39 {
40 EVP_PKEY *pk=NULL, *pk_back = key;
41 enum passType oldOwnPass = ownPass;
42
43 if (ownPass == x || isPubKey())
44 return;
45
46 try {
47 pk = decryptKey();
48 if (pk == NULL)
49 return;
50
51 key = pk;
52 ownPass = x;
53 encryptKey();
54 }
55 catch (errorEx &err) {
56 if (pk)
57 EVP_PKEY_free(pk);
58 key = pk_back;
59 ownPass = oldOwnPass;
60 throw(err);
61 }
62 }
63
sqlUpdatePrivateKey()64 bool pki_evp::sqlUpdatePrivateKey()
65 {
66 Transaction;
67 if (!TransBegin())
68 return false;
69 XSqlQuery q;
70 SQL_PREPARE(q, "UPDATE private_keys SET private=?, ownPass=? "
71 "WHERE item=?");
72 q.bindValue(0, encKey_b64());
73 q.bindValue(1, ownPass);
74 q.bindValue(2, sqlItemId);
75 AffectedItems(sqlItemId);
76 q.exec();
77
78 encKey.fill(0);
79 encKey.clear();
80
81 if (!q.lastError().isValid() && q.numRowsAffected() == 1) {
82 TransCommit();
83 return true;
84 }
85 return false;
86 }
87
generate(const keyjob & task)88 void pki_evp::generate(const keyjob &task)
89 {
90 Entropy::seed_rng();
91 XcaProgress progress;
92
93 #if OPENSSL_VERSION_NUMBER < 0x10100000L
94 BN_GENCB _bar, *bar = &_bar;
95 #else
96 BN_GENCB *bar = BN_GENCB_new();
97 #endif
98 BN_GENCB_set_old(bar, XcaProgress::inc, &progress);
99
100 switch (task.ktype.type) {
101 case EVP_PKEY_RSA: {
102 RSA *rsakey = RSA_new();
103 BIGNUM *e = BN_new();
104 BN_set_word(e, 0x10001);
105 if (RSA_generate_key_ex(rsakey, task.size, e, bar))
106 EVP_PKEY_assign_RSA(key, rsakey);
107 else
108 RSA_free(rsakey);
109 BN_free(e);
110 break;
111 }
112 case EVP_PKEY_DSA: {
113 DSA *dsakey = DSA_new();
114 if (DSA_generate_parameters_ex(dsakey, task.size, NULL, 0,
115 NULL, NULL, bar) && DSA_generate_key(dsakey))
116 EVP_PKEY_assign_DSA(key, dsakey);
117 else
118 DSA_free(dsakey);
119 break;
120 }
121 #ifndef OPENSSL_NO_EC
122 case EVP_PKEY_EC: {
123 EC_KEY *eckey;
124 EC_GROUP *group = EC_GROUP_new_by_curve_name(task.ec_nid);
125 if (!group)
126 break;
127 eckey = EC_KEY_new();
128 if (eckey == NULL) {
129 EC_GROUP_free(group);
130 break;
131 }
132 EC_GROUP_set_asn1_flag(group, 1);
133 if (EC_KEY_set_group(eckey, group)) {
134 if (EC_KEY_generate_key(eckey)) {
135 EVP_PKEY_assign_EC_KEY(key, eckey);
136 EC_GROUP_free(group);
137 break;
138 }
139 }
140 EC_KEY_free(eckey);
141 EC_GROUP_free(group);
142 break;
143 }
144 #ifdef EVP_PKEY_ED25519
145 case EVP_PKEY_ED25519: {
146 EVP_PKEY *pkey = NULL;
147 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
148 EVP_PKEY_keygen_init(pctx);
149 EVP_PKEY_keygen(pctx, &pkey);
150 EVP_PKEY_CTX_free(pctx);
151 EVP_PKEY_free(key);
152 key = pkey;
153 }
154 #endif
155 #endif
156 }
157 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
158 BN_GENCB_free(bar);
159 #endif
160 isPub = false;
161 pkiSource = generated;
162 pki_openssl_error();
163 encryptKey();
164 }
165
pki_evp(const pki_evp * pk)166 pki_evp::pki_evp(const pki_evp *pk)
167 :pki_key(pk)
168 {
169 init();
170 pki_openssl_error();
171 ownPass = pk->ownPass;
172 isPub = pk->isPub;
173 encKey = pk->getEncKey();
174 }
175
pki_evp(const QString & n,int type)176 pki_evp::pki_evp(const QString &n, int type)
177 :pki_key(n)
178 {
179 init();
180 EVP_PKEY_set_type(key, type);
181 pki_openssl_error();
182 }
183
184 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_PKEY_isPrivKey(EVP_PKEY * key)185 static bool EVP_PKEY_isPrivKey(EVP_PKEY *key)
186 {
187 const BIGNUM *b;
188 int keytype = EVP_PKEY_id(key);
189
190 switch (EVP_PKEY_type(keytype)) {
191 case EVP_PKEY_RSA:
192 RSA_get0_key(EVP_PKEY_get0_RSA(key), NULL, NULL, &b);
193 return b ? true: false;
194 case EVP_PKEY_DSA:
195 DSA_get0_key(EVP_PKEY_get0_DSA(key), NULL, &b);
196 return b ? true: false;
197 #ifndef OPENSSL_NO_EC
198 case EVP_PKEY_EC:
199 return EC_KEY_get0_private_key(
200 EVP_PKEY_get0_EC_KEY(key)) ? true: false;
201 #ifdef EVP_PKEY_ED25519
202 case EVP_PKEY_ED25519: {
203 unsigned char buf[ED25519_KEYLEN];
204 size_t len = sizeof buf;
205 int ret = EVP_PKEY_get_raw_private_key(key, buf, &len);
206 ign_openssl_error();
207 return ret && len == ED25519_KEYLEN;
208 }
209 #endif
210 #endif
211 }
212 return false;
213 }
214
215 #else
216
EVP_PKEY_isPrivKey(EVP_PKEY * key)217 static bool EVP_PKEY_isPrivKey(EVP_PKEY *key)
218 {
219 int keytype;
220
221 keytype = EVP_PKEY_id(key);
222
223 switch (EVP_PKEY_type(keytype)) {
224 case EVP_PKEY_RSA:
225 return key->pkey.rsa->d ? true: false;
226 case EVP_PKEY_DSA:
227 return key->pkey.dsa->priv_key ? true: false;
228 #ifndef OPENSSL_NO_EC
229 case EVP_PKEY_EC:
230 return EC_KEY_get0_private_key(key->pkey.ec) ? true: false;
231 #endif
232 }
233 return false;
234 }
235 #endif
236
pki_evp(EVP_PKEY * pkey)237 pki_evp::pki_evp(EVP_PKEY *pkey)
238 :pki_key()
239 {
240 init();
241 set_EVP_PKEY(pkey);
242 }
243
openssl_pw_error() const244 bool pki_evp::openssl_pw_error() const
245 {
246 switch (ERR_peek_error() & 0xff000fff) {
247 case ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT):
248 case ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_PASSWORD_READ):
249 case ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT):
250 pki_ign_openssl_error();
251 return true;
252 }
253 return false;
254 }
255
fromPEMbyteArray(const QByteArray & ba,const QString & name)256 void pki_evp::fromPEMbyteArray(const QByteArray &ba, const QString &name)
257 {
258 EVP_PKEY *pkey;
259 pass_info p(XCA_TITLE,
260 tr("Please enter the password to decrypt the private key %1.")
261 .arg(name));
262 pkey = load_ssh_ed25519_privatekey(ba, p);
263
264 while (!pkey) {
265 pkey = PEM_read_bio_PrivateKey(BioByteArray(ba).ro(), NULL,
266 PwDialog::pwCallback, &p);
267 if (openssl_pw_error())
268 XCA_PASSWD_ERROR();
269 if (p.getResult() != pw_ok)
270 throw p.getResult();
271 if (pki_ign_openssl_error())
272 break;
273 }
274 if (!pkey) {
275 pki_ign_openssl_error();
276 pkey = PEM_read_bio_PUBKEY(BioByteArray(ba).ro(), NULL, NULL,0);
277 }
278 pki_openssl_error();
279 set_EVP_PKEY(pkey, name);
280 }
281
search_ec_oid(EVP_PKEY * pkey)282 static void search_ec_oid(EVP_PKEY *pkey)
283 {
284 #ifndef OPENSSL_NO_EC
285 EC_KEY *ec;
286 EC_GROUP *builtin;
287 const EC_GROUP *ec_group;
288
289 int keytype = EVP_PKEY_id(pkey);
290
291 if (keytype != EVP_PKEY_EC)
292 return;
293
294 ec = EVP_PKEY_get0_EC_KEY(pkey);
295 if (!ec)
296 return;
297
298 ec_group = EC_KEY_get0_group(ec);
299 if (!ec_group)
300 return;
301 if (EC_GROUP_get_curve_name(ec_group))
302 return;
303 /* There is an EC_GROUP with a missing OID
304 * because of explicit parameters */
305 foreach(builtin_curve curve, builtinCurves) {
306 builtin = EC_GROUP_new_by_curve_name(curve.nid);
307 if (EC_GROUP_cmp(builtin, ec_group, NULL) == 0) {
308 EC_GROUP_set_curve_name((EC_GROUP *)ec_group, curve.nid);
309 EC_GROUP_set_asn1_flag((EC_GROUP *)ec_group, 1);
310 EC_GROUP_free(builtin);
311 break;
312 }
313 EC_GROUP_free(builtin);
314 }
315 #else
316 (void)pkey;
317 #endif
318 }
319
set_EVP_PKEY(EVP_PKEY * pkey,QString name)320 void pki_evp::set_EVP_PKEY(EVP_PKEY *pkey, QString name)
321 {
322 if (!pkey)
323 return;
324 if (!verify(pkey)) {
325 pki_ign_openssl_error();
326 EVP_PKEY_free(pkey);
327 throw errorEx(tr("The key from file '%1' is incomplete or inconsistent.").arg(name));
328 }
329 if (key)
330 EVP_PKEY_free(key);
331 key = pkey;
332 isPub = !EVP_PKEY_isPrivKey(key);
333 if (!isPub)
334 bogusEncryptKey();
335 search_ec_oid(pkey);
336
337 autoIntName(name);
338 setFilename(name);
339 pki_openssl_error();
340 }
341
load_ssh_ed25519_privatekey(const QByteArray & ba,const pass_info & p)342 EVP_PKEY *pki_evp::load_ssh_ed25519_privatekey(const QByteArray &ba,
343 const pass_info &p)
344 {
345 EVP_PKEY *pkey = NULL;
346 unsigned char *pdata;
347 long plen;
348 QByteArray chunk, enc_algo, kdfname, kdf, pub, priv;
349
350 (void)p; // Will be used later for decryption
351 if (!PEM_bytes_read_bio(&pdata, &plen, NULL, PEM_STRING_OPENSSH_KEY,
352 BioByteArray(ba).ro(), NULL, NULL))
353 return NULL;
354
355 QByteArray content((const char*)pdata, plen);
356 OPENSSL_free(pdata);
357
358 if (!content.startsWith("openssh-key-v1") ||
359 // also check trailing \0
360 content.constData()[sizeof "openssh-key-v1" -1])
361 return NULL;
362
363 content.remove(0, sizeof "openssh-key-v1");
364 // encryption: "none", "aes256-ctr"
365 enc_algo = ssh_key_next_chunk(&content);
366 // KDFName "bcrypt"
367 kdfname = ssh_key_next_chunk(&content);
368 kdf = ssh_key_next_chunk(&content);
369
370 if (enc_algo != "none" || kdfname != "none") {
371 qCritical("Encrypted SSH ED25519 keys not supported, yet");
372 return NULL;
373 }
374 // check bytes 00 00 00 01
375 const char *d = content.constData();
376 if (d[0] || d[1] || d[2] || d[3] != 1)
377 return NULL;
378 content.remove(0, 4);
379 // Handle first occurance of the public key
380 pub = ssh_key_next_chunk(&content);
381 ssh_key_check_chunk(&pub, "ssh-ed25519");
382 pub = ssh_key_next_chunk(&pub);
383 if (pub.count() != ED25519_KEYLEN)
384 return NULL;
385
386 // Followed by the private key
387 priv = ssh_key_next_chunk(&content);
388 // Drop 64bit random nonce
389 priv.remove(0, 8);
390
391 ssh_key_check_chunk(&priv, "ssh-ed25519");
392 // The first pubkey must match the second occurance
393 // in front of the private one
394 if (pub != ssh_key_next_chunk(&priv))
395 return NULL;
396 priv = ssh_key_next_chunk(&priv);
397 // The private key is concatenated by the public key in one chunk
398 if (priv.count() != 2 * ED25519_KEYLEN)
399 return NULL;
400 // The last ED25519_KEYLEN bytes must match the public key
401 if (pub != priv.mid(ED25519_KEYLEN))
402 return NULL;
403 // The first ED25519_KEYLEN octets are the private key
404 #ifndef OPENSSL_NO_EC
405 #ifdef EVP_PKEY_ED25519
406 pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
407 (const unsigned char *)priv.constData(), ED25519_KEYLEN);
408 #endif
409 #endif
410 pki_openssl_error();
411 return pkey;
412 }
413
fload(const QString & fname)414 void pki_evp::fload(const QString &fname)
415 {
416 pass_info p(XCA_TITLE, tr("Please enter the password to decrypt the private key from file:\n%1").
417 arg(compressFilename(fname)));
418 pem_password_cb *cb = PwDialog::pwCallback;
419
420 pki_ign_openssl_error();
421 XFile file(fname);
422 file.open_read();
423 EVP_PKEY *pkey;
424
425 do {
426 pkey = PEM_read_PrivateKey(file.fp(), NULL, cb, &p);
427 if (openssl_pw_error())
428 XCA_PASSWD_ERROR();
429 if (p.getResult() != pw_ok)
430 throw p.getResult();
431 if (pki_ign_openssl_error())
432 break;
433 file.retry_read();
434 } while (!pkey);
435
436 if (!pkey) {
437 pki_ign_openssl_error();
438 file.retry_read();
439 pkey = d2i_PrivateKey_fp(file.fp(), NULL);
440 }
441 if (!pkey) {
442 pki_ign_openssl_error();
443 file.retry_read();
444 pkey = d2i_PKCS8PrivateKey_fp(file.fp(), NULL, cb, &p);
445 }
446 if (!pkey) {
447 PKCS8_PRIV_KEY_INFO *p8inf;
448 pki_ign_openssl_error();
449 file.retry_read();
450 p8inf = d2i_PKCS8_PRIV_KEY_INFO_fp(file.fp(), NULL);
451 if (p8inf) {
452 pkey = EVP_PKCS82PKEY(p8inf);
453 PKCS8_PRIV_KEY_INFO_free(p8inf);
454 }
455 }
456 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
457 if (!pkey) {
458 pki_ign_openssl_error();
459 file.retry_read();
460 pkey = b2i_PVK_bio(file.bio(), cb, &p);
461 }
462 if (!pkey) {
463 pki_ign_openssl_error();
464 file.retry_read();
465 pkey = load_ssh_ed25519_privatekey(file.read(10000), p);
466 }
467 #endif
468 if (!pkey) {
469 pki_ign_openssl_error();
470 file.retry_read();
471 pkey = PEM_read_PUBKEY(file.fp(), NULL, cb, &p);
472 }
473 if (!pkey) {
474 pki_ign_openssl_error();
475 file.retry_read();
476 pkey = d2i_PUBKEY_fp(file.fp(), NULL);
477 }
478 if (!pkey) {
479 pki_ign_openssl_error();
480 file.retry_read();
481 pkey = load_ssh2_key(file);
482 }
483 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
484 if (!pkey) {
485 pki_ign_openssl_error();
486 file.retry_read();
487 pkey = b2i_PublicKey_bio(file.bio());
488 }
489 #endif
490 if (pki_ign_openssl_error() || !pkey) {
491 if (pkey)
492 EVP_PKEY_free(pkey);
493 throw errorEx(tr("Unable to load the private key in file %1. Tried PEM and DER private, public, PKCS#8 key types and SSH2 format.").arg(fname));
494 }
495 set_EVP_PKEY(pkey, fname);
496 }
497
fromData(const unsigned char * p,db_header_t * head)498 void pki_evp::fromData(const unsigned char *p, db_header_t *head)
499 {
500 int version, type, size;
501 void *ptr = NULL;
502
503 if (key)
504 EVP_PKEY_free(key);
505 key = NULL;
506
507 size = head->len - sizeof(db_header_t);
508 version = head->version;
509
510 QByteArray ba((const char*)p, size);
511
512 type = db::intFromData(ba);
513 ownPass = (enum passType)db::intFromData(ba);
514 if (version < 2) {
515 d2i_old(ba, type);
516 } else {
517 d2i(ba);
518 }
519 pki_openssl_error();
520
521 if (key)
522 ptr = EVP_PKEY_get0(key);
523 if (!ptr)
524 throw errorEx(tr("Ignoring unsupported private key"));
525
526 encKey = ba;
527 isPub = encKey.size() == 0;
528 }
529
decryptKey() const530 EVP_PKEY *pki_evp::decryptKey() const
531 {
532 Passwd ownPassBuf;
533 int ret;
534
535 if (isPubKey()) {
536 QByteArray ba = i2d_bytearray(I2D_VOID(i2d_PUBKEY), key);
537 return (EVP_PKEY*)d2i_bytearray(D2I_VOID(d2i_PUBKEY), ba);
538 }
539 /* This key has its own password */
540 if (ownPass == ptPrivate) {
541 pass_info pi(XCA_TITLE, tr("Please enter the password to decrypt the private key: '%1'").arg(getIntName()));
542 ret = PwDialog::execute(&pi, &ownPassBuf, false);
543 if (ret != 1)
544 throw errorEx(tr("Password input aborted"),
545 getClassName());
546 } else if (ownPass == ptBogus) { // BOGUS pass
547 ownPassBuf = "Bogus";
548 } else {
549 ownPassBuf = passwd;
550 while (passHash.isEmpty() ||
551 (sha512passwT(ownPassBuf, passHash) != passHash &&
552 sha512passwd(ownPassBuf, passHash) != passHash))
553 {
554 pass_info p(XCA_TITLE, tr("Please enter the database password for decrypting the key '%1'").arg(getIntName()));
555 ret = PwDialog::execute(&p, &ownPassBuf,
556 passHash.isEmpty());
557 if (ret != 1)
558 throw errorEx(tr("Password input aborted"),
559 getClassName());
560 }
561 }
562 QByteArray myencKey = getEncKey();
563 qDebug() << "myencKey.count()"<<myencKey.count();
564 if (myencKey.count() == 0)
565 return NULL;
566 EVP_PKEY *priv = NULL;
567 X509_SIG *p8 = d2i_PKCS8_bio(BioByteArray(myencKey).ro(), NULL);
568 if (p8) {
569 PKCS8_PRIV_KEY_INFO *p8inf = PKCS8_decrypt(p8,
570 ownPassBuf.constData(), ownPassBuf.size());
571 if (p8inf) {
572 priv = EVP_PKCS82PKEY(p8inf);
573 PKCS8_PRIV_KEY_INFO_free(p8inf);
574 }
575 X509_SIG_free(p8);
576 }
577 if (priv)
578 return priv;
579 pki_ign_openssl_error();
580 return legacyDecryptKey(myencKey, ownPassBuf);
581 }
582
legacyDecryptKey(QByteArray & myencKey,Passwd & ownPassBuf) const583 EVP_PKEY *pki_evp::legacyDecryptKey(QByteArray &myencKey,
584 Passwd &ownPassBuf) const
585 {
586 unsigned char *p;
587 const unsigned char *p1;
588 int outl, decsize;
589 unsigned char iv[EVP_MAX_IV_LENGTH];
590 unsigned char ckey[EVP_MAX_KEY_LENGTH];
591
592 EVP_PKEY *tmpkey;
593 EVP_CIPHER_CTX *ctx;
594 const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
595 p = (unsigned char *)OPENSSL_malloc(myencKey.count());
596 check_oom(p);
597 pki_openssl_error();
598 p1 = p;
599 memset(iv, 0, EVP_MAX_IV_LENGTH);
600
601 memcpy(iv, myencKey.constData(), 8); /* recover the iv */
602 /* generate the key */
603 EVP_BytesToKey(cipher, EVP_sha1(), iv,
604 ownPassBuf.constUchar(), ownPassBuf.size(), 1, ckey, NULL);
605 ctx = EVP_CIPHER_CTX_new();
606 EVP_DecryptInit(ctx, cipher, ckey, iv);
607 EVP_DecryptUpdate(ctx, p , &outl,
608 (const unsigned char*)myencKey.constData() +8,
609 myencKey.count() -8);
610 decsize = outl;
611 EVP_DecryptFinal_ex(ctx, p + decsize , &outl);
612
613 EVP_CIPHER_CTX_cleanup(ctx);
614 decsize += outl;
615 pki_openssl_error();
616 tmpkey = d2i_PrivateKey(getKeyType(), NULL, &p1, decsize);
617 pki_openssl_error();
618 OPENSSL_cleanse(p, myencKey.count());
619 OPENSSL_free(p);
620 EVP_CIPHER_CTX_free(ctx);
621
622 pki_openssl_error();
623 if (EVP_PKEY_type(getKeyType()) == EVP_PKEY_RSA) {
624 RSA *rsa = EVP_PKEY_get0_RSA(tmpkey);
625 RSA_blinding_on(rsa, NULL);
626 }
627 myencKey.fill(0);
628 return tmpkey;
629 }
630
priv2pub(EVP_PKEY * key)631 EVP_PKEY *pki_evp::priv2pub(EVP_PKEY* key)
632 {
633 int keylen;
634 unsigned char *p, *p1;
635 EVP_PKEY *pubkey;
636
637 keylen = i2d_PUBKEY(key, NULL);
638 p1 = p = (unsigned char *)OPENSSL_malloc(keylen);
639 check_oom(p);
640
641 /* convert rsa/dsa/ec to Pubkey */
642 keylen = i2d_PUBKEY(key, &p);
643 pki_openssl_error();
644 p = p1;
645 pubkey = d2i_PUBKEY(NULL, (const unsigned char**)&p, keylen);
646 OPENSSL_free(p1);
647 pki_openssl_error();
648 return pubkey;
649 }
650
encryptKey(const char * password)651 void pki_evp::encryptKey(const char *password)
652 {
653 Passwd ownPassBuf;
654
655 pki_openssl_error();
656 /* This key has its own, private password */
657 if (ownPass == ptPrivate) {
658 int ret;
659 pass_info p(XCA_TITLE, tr("Please enter the password to protect the private key: '%1'").
660 arg(getIntName()));
661 ret = PwDialog::execute(&p, &ownPassBuf, true);
662 if (ret != 1)
663 throw errorEx("Password input aborted", getClassName());
664 pki_openssl_error();
665 } else if (ownPass == ptBogus) { // BOGUS password
666 ownPassBuf = "Bogus";
667 pki_openssl_error();
668 } else {
669 if (password) {
670 /* use the password parameter
671 * if this is a common password */
672 ownPassBuf = password;
673 pki_openssl_error();
674 } else {
675 int ret = 0;
676 ownPassBuf = passwd;
677 pass_info p(XCA_TITLE, tr("Please enter the database password for encrypting the key"));
678 while (passHash.isEmpty() ||
679 (sha512passwT(ownPassBuf, passHash) != passHash &&
680 sha512passwd(ownPassBuf, passHash) != passHash))
681 {
682 ret = PwDialog::execute(&p, &ownPassBuf,
683 passHash.isEmpty());
684 if (ret != 1)
685 throw errorEx("Password input aborted",
686 getClassName());
687 }
688 }
689 }
690
691 /* Convert private key to DER(PKCS8-aes) */
692 BioByteArray bba;
693 i2d_PKCS8PrivateKey_bio(bba, key, EVP_aes_256_cbc(),
694 ownPassBuf.data(), ownPassBuf.size(), NULL, 0);
695 pki_openssl_error();
696 encKey = bba;
697
698 /* Replace private key by public key and
699 have the encrypted private in "encKey"
700 */
701 EVP_PKEY *pkey1 = priv2pub(key);
702 check_oom(pkey1);
703 EVP_PKEY_free(key);
704 key = pkey1;
705 pki_openssl_error();
706 }
707
set_evp_key(EVP_PKEY * pkey)708 void pki_evp::set_evp_key(EVP_PKEY *pkey)
709 {
710 if (key)
711 free(key);
712 key = pkey;
713 }
714
bogusEncryptKey()715 void pki_evp::bogusEncryptKey()
716 {
717 ownPass = ptBogus;
718 isPub = false;
719 encryptKey();
720 }
721
~pki_evp()722 pki_evp::~pki_evp()
723 {
724 encKey.fill(0);
725 }
726
insertSqlData()727 QSqlError pki_evp::insertSqlData()
728 {
729 XSqlQuery q;
730 QSqlError e = pki_key::insertSqlData();
731 if (e.isValid())
732 return e;
733 if (isPubKey())
734 return QSqlError();
735
736 SQL_PREPARE(q, "INSERT INTO private_keys (item, ownPass, private) "
737 "VALUES (?, ?, ?)");
738 q.bindValue(0, sqlItemId);
739 q.bindValue(1, ownPass);
740 q.bindValue(2, encKey_b64());
741 q.exec();
742 encKey.fill(0);
743 encKey.clear();
744 return q.lastError();
745 }
746
restoreSql(const QSqlRecord & rec)747 void pki_evp::restoreSql(const QSqlRecord &rec)
748 {
749 pki_key::restoreSql(rec);
750 isPub = rec.isNull(VIEW_private_ownpass);
751 if (!isPub)
752 ownPass =(enum passType)rec.value(VIEW_private_ownpass).toInt();
753 }
754
getEncKey() const755 QByteArray pki_evp::getEncKey() const
756 {
757 XSqlQuery q;
758 QSqlError e;
759 QByteArray ba;
760
761 if (encKey.count() > 0 || !sqlItemId.isValid())
762 return encKey;
763
764 SQL_PREPARE(q, "SELECT private FROM private_keys WHERE item=?");
765 q.bindValue(0, sqlItemId);
766 q.exec();
767 e = q.lastError();
768 if (e.isValid() || !q.first())
769 return QByteArray();
770 return QByteArray::fromBase64(q.value(0).toByteArray().trimmed());
771 }
772
deleteSqlData()773 QSqlError pki_evp::deleteSqlData()
774 {
775 XSqlQuery q;
776 QSqlError e = pki_key::deleteSqlData();
777 if (e.isValid())
778 return e;
779 SQL_PREPARE(q, "DELETE FROM private_keys WHERE item=?");
780 q.bindValue(0, sqlItemId);
781 q.exec();
782 return q.lastError();
783 }
784
writePKCS8(XFile & file,const EVP_CIPHER * enc,pem_password_cb * cb,bool pem) const785 void pki_evp::writePKCS8(XFile &file, const EVP_CIPHER *enc,
786 pem_password_cb *cb, bool pem) const
787 {
788 pass_info p(XCA_TITLE,
789 tr("Please enter the password protecting the PKCS#8 key '%1'")
790 .arg(getIntName()));
791 EVP_PKEY *pkey = decryptKey();
792 if (!pkey) {
793 pki_openssl_error();
794 return;
795 }
796 if (pem) {
797 PEM_file_comment(file);
798 PEM_write_PKCS8PrivateKey(file.fp(), pkey, enc, NULL, 0,cb,&p);
799 } else {
800 i2d_PKCS8PrivateKey_fp(file.fp(), pkey, enc, NULL, 0, cb, &p);
801 }
802 EVP_PKEY_free(pkey);
803 }
804
writePVKprivate(XFile & file,pem_password_cb * cb) const805 void pki_evp::writePVKprivate(XFile &file, pem_password_cb *cb) const
806 {
807 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
808 pass_info p(XCA_TITLE, tr("Please enter the password protecting the Microsoft PVK key '%1'").arg(getIntName()));
809
810 int enc = cb ? 2 /* pvk-strong */ : 0 /* pvk-none */;
811 EVP_PKEY *pkey = decryptKey();
812 if (!pkey) {
813 pki_openssl_error();
814 return;
815 }
816 /* In case of success! the error
817 * PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE)
818 * is set. Workaround this behavior */
819 if (i2b_PVK_bio(file.bio(), pkey, enc, cb, &p) == -1) {
820 pki_openssl_error();
821 PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
822 pki_openssl_error();
823 }
824 ign_openssl_error();
825 EVP_PKEY_free(pkey);
826 #else
827 (void)file;
828 (void)cb;
829 throw errorEx("Internal Error");
830 #endif
831 }
mycb(char * buf,int size,int,void *)832 static int mycb(char *buf, int size, int, void *)
833 {
834 strncpy(buf, pki_evp::passwd, size);
835 return strlen(pki_evp::passwd);
836 }
837
writeDefault(const QString & dirname) const838 void pki_evp::writeDefault(const QString &dirname) const
839 {
840 XFile file(get_dump_filename(dirname, ".pem"));
841 file.open_key();
842 writeKey(file, pki_evp::passwd[0] ? EVP_des_ede3_cbc() : NULL,
843 mycb, true);
844 }
845
846 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
PEM_write_bio_PrivateKey_traditional(BIO * bp,EVP_PKEY * x,const EVP_CIPHER * enc,unsigned char * kstr,int klen,pem_password_cb * cb,void * u)847 int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x,
848 const EVP_CIPHER *enc,
849 unsigned char *kstr, int klen,
850 pem_password_cb *cb, void *u)
851 {
852 QString pem = keytype::byPKEY(x).traditionalPemName();
853
854 return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
855 pem.toLatin1(), bp, (char*)x, enc, kstr, klen, cb, u);
856 }
857 #endif
858
writeKey(XFile & file,const EVP_CIPHER * enc,pem_password_cb * cb,bool pem) const859 void pki_evp::writeKey(XFile &file, const EVP_CIPHER *enc,
860 pem_password_cb *cb, bool pem) const
861 {
862 pass_info p(XCA_TITLE,
863 tr("Please enter the export password for the private key '%1'")
864 .arg(getIntName()));
865
866 if (isPubKey()) {
867 writePublic(file, pem);
868 return;
869 }
870 EVP_PKEY *pkey = key ? decryptKey() : NULL;
871 if (!pkey) {
872 pki_openssl_error();
873 return;
874 }
875 if (pem) {
876 PEM_file_comment(file);
877 PEM_write_bio_PrivateKey_traditional(file.bio(), pkey, enc,
878 NULL, 0, cb, &p);
879 } else {
880 i2d_PrivateKey_fp(file.fp(), pkey);
881 }
882 EVP_PKEY_free(pkey);
883 pki_openssl_error();
884 }
885
verify_priv(EVP_PKEY * pkey) const886 bool pki_evp::verify_priv(EVP_PKEY *pkey) const
887 {
888 bool verify = true;
889 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
890 unsigned char data[32], sig[1024];
891 size_t datalen = sizeof data, siglen = sizeof sig;
892 EVP_MD_CTX *ctx = NULL;
893 const EVP_MD *md = EVP_sha256();
894 EVP_PKEY_CTX *pkctx = NULL;
895
896 if (!EVP_PKEY_isPrivKey(pkey))
897 return true;
898 do {
899 ctx = EVP_MD_CTX_new();
900 pki_ign_openssl_error();
901 RAND_bytes(data, datalen);
902 check_oom(ctx);
903 verify = false;
904
905 /* Sign some random data in "data" */
906 #ifdef EVP_PKEY_ED25519
907 if (EVP_PKEY_id(pkey) == EVP_PKEY_ED25519)
908 md = NULL;
909 #endif
910 if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
911 break;
912
913 if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA)
914 EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PADDING);
915
916 if (!EVP_DigestSign(ctx, sig, &siglen, data, datalen))
917 break;
918
919 /* Verify the signature */
920 if (!EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey))
921 break;
922
923 if (EVP_DigestVerify(ctx, sig, siglen, data, datalen) != 1)
924 break;
925
926 verify = true;
927 } while (0);
928
929 if (ctx)
930 EVP_MD_CTX_free(ctx);
931 #endif
932 if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_isPrivKey(pkey)) {
933 RSA *rsa = EVP_PKEY_get0_RSA(pkey);
934 if (RSA_check_key(rsa) != 1)
935 verify = false;
936 }
937 pki_openssl_error();
938 return verify;
939 }
940
getIcon(const dbheader * hd) const941 QVariant pki_evp::getIcon(const dbheader *hd) const
942 {
943 if (hd->id != HD_internal_name)
944 return QVariant();
945
946 return QVariant(QPixmap(isPubKey() ? ":pubkeyIco" : ":keyIco"));
947 }
948
md5passwd(QByteArray pass)949 QString pki_evp::md5passwd(QByteArray pass)
950 {
951 return formatHash(Digest(pass, EVP_md5()));
952 }
953
_sha512passwd(QByteArray pass,QString salt,int size,int repeat)954 QString pki_evp::_sha512passwd(QByteArray pass, QString salt,
955 int size, int repeat)
956 {
957 if (salt.length() < size)
958 return QString();
959
960 salt = salt.left(size);
961 pass = salt.toLatin1() + pass;
962
963 while (repeat--)
964 pass = Digest(pass, EVP_sha512());
965
966 return salt + formatHash(pass, "");
967 }
968
sha512passwd(QByteArray pass,QString salt)969 QString pki_evp::sha512passwd(QByteArray pass, QString salt)
970 {
971 return _sha512passwd(pass, salt, 5, 1);
972 }
973
sha512passwT(QByteArray pass,QString salt)974 QString pki_evp::sha512passwT(QByteArray pass, QString salt)
975 {
976 return _sha512passwd(pass, salt, 17, 8000);
977 }
978