Skip to content

Commit 5866086

Browse files
Lei Hemstsirkin
authored andcommitted
crypto: Support export akcipher to pkcs8
crypto: support export RSA private keys with PKCS#8 standard. So that users can upload this private key to linux kernel. Signed-off-by: lei he <[email protected]> Message-Id: <[email protected]> Reviewed-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> Reviewed-by: Daniel P. Berrangé <[email protected]>
1 parent 3b34cca commit 5866086

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed

crypto/akcipher.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qemu/osdep.h"
2323
#include "crypto/akcipher.h"
2424
#include "akcipherpriv.h"
25+
#include "der.h"
26+
#include "rsakey.h"
2527

2628
#if defined(CONFIG_GCRYPT)
2729
#include "akcipher-gcrypt.c.inc"
@@ -106,3 +108,19 @@ void qcrypto_akcipher_free(QCryptoAkCipher *akcipher)
106108

107109
drv->free(akcipher);
108110
}
111+
112+
int qcrypto_akcipher_export_p8info(const QCryptoAkCipherOptions *opts,
113+
uint8_t *key, size_t keylen,
114+
uint8_t **dst, size_t *dst_len,
115+
Error **errp)
116+
{
117+
switch (opts->alg) {
118+
case QCRYPTO_AKCIPHER_ALG_RSA:
119+
qcrypto_akcipher_rsakey_export_p8info(key, keylen, dst, dst_len);
120+
return 0;
121+
122+
default:
123+
error_setg(errp, "Unsupported algorithm: %u", opts->alg);
124+
return -1;
125+
}
126+
}

crypto/rsakey.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
*
2020
*/
2121

22+
#include "qemu/osdep.h"
23+
#include "der.h"
2224
#include "rsakey.h"
2325

2426
void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *rsa_key)
@@ -37,6 +39,46 @@ void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *rsa_key)
3739
g_free(rsa_key);
3840
}
3941

42+
/**
43+
* PKCS#8 private key info for RSA
44+
*
45+
* PrivateKeyInfo ::= SEQUENCE {
46+
* version INTEGER,
47+
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
48+
* privateKey OCTET STRING,
49+
* attributes [0] IMPLICIT Attributes OPTIONAL
50+
* }
51+
*/
52+
void qcrypto_akcipher_rsakey_export_p8info(const uint8_t *key,
53+
size_t keylen,
54+
uint8_t **dst,
55+
size_t *dlen)
56+
{
57+
QCryptoEncodeContext *ctx = qcrypto_der_encode_ctx_new();
58+
uint8_t version = 0;
59+
60+
qcrypto_der_encode_seq_begin(ctx);
61+
62+
/* version */
63+
qcrypto_der_encode_int(ctx, &version, sizeof(version));
64+
65+
/* algorithm identifier */
66+
qcrypto_der_encode_seq_begin(ctx);
67+
qcrypto_der_encode_oid(ctx, (uint8_t *)QCRYPTO_OID_rsaEncryption,
68+
sizeof(QCRYPTO_OID_rsaEncryption) - 1);
69+
qcrypto_der_encode_null(ctx);
70+
qcrypto_der_encode_seq_end(ctx);
71+
72+
/* RSA private key */
73+
qcrypto_der_encode_octet_str(ctx, key, keylen);
74+
75+
qcrypto_der_encode_seq_end(ctx);
76+
77+
*dlen = qcrypto_der_encode_ctx_buffer_len(ctx);
78+
*dst = g_malloc(*dlen);
79+
qcrypto_der_encode_ctx_flush_and_free(ctx, *dst);
80+
}
81+
4082
#if defined(CONFIG_NETTLE) && defined(CONFIG_HOGWEED)
4183
#include "rsakey-nettle.c.inc"
4284
#else

crypto/rsakey.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#ifndef QCRYPTO_RSAKEY_H
2323
#define QCRYPTO_RSAKEY_H
2424

25-
#include "qemu/osdep.h"
2625
#include "qemu/host-utils.h"
2726
#include "crypto/akcipher.h"
2827

@@ -84,6 +83,16 @@ QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
8483
QCryptoAkCipherKeyType type,
8584
const uint8_t *key, size_t keylen, Error **errp);
8685

86+
/**
87+
* qcrypto_akcipher_rsakey_export_as_p8info:
88+
*
89+
* Export RSA private key to PKCS#8 private key info.
90+
*/
91+
void qcrypto_akcipher_rsakey_export_p8info(const uint8_t *key,
92+
size_t keylen,
93+
uint8_t **dst,
94+
size_t *dlen);
95+
8796
void qcrypto_akcipher_rsakey_free(QCryptoAkCipherRSAKey *key);
8897

8998
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoAkCipherRSAKey,

include/crypto/akcipher.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,27 @@ int qcrypto_akcipher_max_dgst_len(QCryptoAkCipher *akcipher);
153153
*/
154154
void qcrypto_akcipher_free(QCryptoAkCipher *akcipher);
155155

156+
/**
157+
* qcrypto_akcipher_export_p8info:
158+
* @opts: the options of the akcipher to be exported.
159+
* @key: the original key of the akcipher to be exported.
160+
* @keylen: length of the 'key'
161+
* @dst: output parameter, if export succeed, *dst is set to the
162+
* PKCS#8 encoded private key, caller MUST free this key with
163+
* g_free after use.
164+
* @dst_len: output parameter, indicates the length of PKCS#8 encoded
165+
* key.
166+
*
167+
* Export the akcipher into DER encoded pkcs#8 private key info, expects
168+
* |key| stores a valid asymmetric PRIVATE key.
169+
*
170+
* Returns: 0 for succeed, otherwise -1 is returned.
171+
*/
172+
int qcrypto_akcipher_export_p8info(const QCryptoAkCipherOptions *opts,
173+
uint8_t *key, size_t keylen,
174+
uint8_t **dst, size_t *dst_len,
175+
Error **errp);
176+
156177
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoAkCipher, qcrypto_akcipher_free)
157178

158179
#endif /* QCRYPTO_AKCIPHER_H */

0 commit comments

Comments
 (0)