14c5e512eSLei He/* 24c5e512eSLei He * QEMU Crypto akcipher algorithms 34c5e512eSLei He * 44c5e512eSLei He * Copyright (c) 2022 Bytedance 54c5e512eSLei He * Author: lei he <helei.sig11@bytedance.com> 64c5e512eSLei He * 74c5e512eSLei He * This library is free software; you can redistribute it and/or 84c5e512eSLei He * modify it under the terms of the GNU Lesser General Public 94c5e512eSLei He * License as published by the Free Software Foundation; either 104c5e512eSLei He * version 2.1 of the License, or (at your option) any later version. 114c5e512eSLei He * 124c5e512eSLei He * This library is distributed in the hope that it will be useful, 134c5e512eSLei He * but WITHOUT ANY WARRANTY; without even the implied warranty of 144c5e512eSLei He * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 154c5e512eSLei He * Lesser General Public License for more details. 164c5e512eSLei He * 174c5e512eSLei He * You should have received a copy of the GNU Lesser General Public 184c5e512eSLei He * License along with this library; if not, see <http://www.gnu.org/licenses/>. 194c5e512eSLei He * 204c5e512eSLei He */ 214c5e512eSLei He 224c5e512eSLei He#include "der.h" 234c5e512eSLei He#include "rsakey.h" 244c5e512eSLei He 254c5e512eSLei Hestatic int extract_mpi(void *ctx, const uint8_t *value, 264c5e512eSLei He size_t vlen, Error **errp) 274c5e512eSLei He{ 284c5e512eSLei He QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx; 294c5e512eSLei He if (vlen == 0) { 304c5e512eSLei He error_setg(errp, "Empty mpi field"); 314c5e512eSLei He return -1; 324c5e512eSLei He } 334c5e512eSLei He mpi->data = g_memdup2(value, vlen); 344c5e512eSLei He mpi->len = vlen; 354c5e512eSLei He return 0; 364c5e512eSLei He} 374c5e512eSLei He 384c5e512eSLei Hestatic int extract_version(void *ctx, const uint8_t *value, 394c5e512eSLei He size_t vlen, Error **errp) 404c5e512eSLei He{ 414c5e512eSLei He uint8_t *version = (uint8_t *)ctx; 424c5e512eSLei He if (vlen != 1 || *value > 1) { 434c5e512eSLei He error_setg(errp, "Invalid rsakey version"); 444c5e512eSLei He return -1; 454c5e512eSLei He } 464c5e512eSLei He *version = *value; 474c5e512eSLei He return 0; 484c5e512eSLei He} 494c5e512eSLei He 504c5e512eSLei Hestatic int extract_seq_content(void *ctx, const uint8_t *value, 514c5e512eSLei He size_t vlen, Error **errp) 524c5e512eSLei He{ 534c5e512eSLei He const uint8_t **content = (const uint8_t **)ctx; 544c5e512eSLei He if (vlen == 0) { 554c5e512eSLei He error_setg(errp, "Empty sequence"); 564c5e512eSLei He return -1; 574c5e512eSLei He } 584c5e512eSLei He *content = value; 594c5e512eSLei He return 0; 604c5e512eSLei He} 614c5e512eSLei He 624c5e512eSLei He/** 634c5e512eSLei He * 644c5e512eSLei He * RsaPubKey ::= SEQUENCE { 654c5e512eSLei He * n INTEGER 664c5e512eSLei He * e INTEGER 674c5e512eSLei He * } 684c5e512eSLei He */ 694c5e512eSLei Hestatic QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_public_key_parse( 704c5e512eSLei He const uint8_t *key, size_t keylen, Error **errp) 714c5e512eSLei He{ 724c5e512eSLei He QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1); 734c5e512eSLei He const uint8_t *seq; 744c5e512eSLei He size_t seq_length; 754c5e512eSLei He int decode_ret; 764c5e512eSLei He 774c5e512eSLei He decode_ret = qcrypto_der_decode_seq(&key, &keylen, 784c5e512eSLei He extract_seq_content, &seq, errp); 794c5e512eSLei He if (decode_ret < 0 || keylen != 0) { 804c5e512eSLei He goto error; 814c5e512eSLei He } 824c5e512eSLei He seq_length = decode_ret; 834c5e512eSLei He 844c5e512eSLei He if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 854c5e512eSLei He &rsa->n, errp) < 0 || 864c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 874c5e512eSLei He &rsa->e, errp) < 0) { 884c5e512eSLei He goto error; 894c5e512eSLei He } 904c5e512eSLei He if (seq_length != 0) { 91e158f8e9SMarkus Armbruster error_setg(errp, "Invalid RSA public key"); 924c5e512eSLei He goto error; 934c5e512eSLei He } 944c5e512eSLei He 954c5e512eSLei He return rsa; 964c5e512eSLei He 974c5e512eSLei Heerror: 984c5e512eSLei He qcrypto_akcipher_rsakey_free(rsa); 994c5e512eSLei He return NULL; 1004c5e512eSLei He} 1014c5e512eSLei He 1024c5e512eSLei He/** 1034c5e512eSLei He * RsaPrivKey ::= SEQUENCE { 1044c5e512eSLei He * version INTEGER 1054c5e512eSLei He * n INTEGER 1064c5e512eSLei He * e INTEGER 1074c5e512eSLei He * d INTEGER 1084c5e512eSLei He * p INTEGER 1094c5e512eSLei He * q INTEGER 1104c5e512eSLei He * dp INTEGER 1114c5e512eSLei He * dq INTEGER 1124c5e512eSLei He * u INTEGER 1134c5e512eSLei He * otherPrimeInfos OtherPrimeInfos OPTIONAL 1144c5e512eSLei He * } 1154c5e512eSLei He */ 1164c5e512eSLei Hestatic QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_private_key_parse( 1174c5e512eSLei He const uint8_t *key, size_t keylen, Error **errp) 1184c5e512eSLei He{ 1194c5e512eSLei He QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1); 1204c5e512eSLei He uint8_t version; 1214c5e512eSLei He const uint8_t *seq; 1224c5e512eSLei He int decode_ret; 1234c5e512eSLei He size_t seq_length; 1244c5e512eSLei He 1254c5e512eSLei He decode_ret = qcrypto_der_decode_seq(&key, &keylen, extract_seq_content, 1264c5e512eSLei He &seq, errp); 1274c5e512eSLei He if (decode_ret < 0 || keylen != 0) { 1284c5e512eSLei He goto error; 1294c5e512eSLei He } 1304c5e512eSLei He seq_length = decode_ret; 1314c5e512eSLei He 1324c5e512eSLei He decode_ret = qcrypto_der_decode_int(&seq, &seq_length, extract_version, 1334c5e512eSLei He &version, errp); 1344c5e512eSLei He 1354c5e512eSLei He if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 1364c5e512eSLei He &rsa->n, errp) < 0 || 1374c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 1384c5e512eSLei He &rsa->e, errp) < 0 || 1394c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 1404c5e512eSLei He &rsa->d, errp) < 0 || 1414c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->p, 1424c5e512eSLei He errp) < 0 || 1434c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->q, 1444c5e512eSLei He errp) < 0 || 1454c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dp, 1464c5e512eSLei He errp) < 0 || 1474c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dq, 1484c5e512eSLei He errp) < 0 || 1494c5e512eSLei He qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->u, 1504c5e512eSLei He errp) < 0) { 1514c5e512eSLei He goto error; 1524c5e512eSLei He } 1534c5e512eSLei He 1544c5e512eSLei He /** 1554c5e512eSLei He * According to the standard, otherPrimeInfos must be present for version 1. 1564c5e512eSLei He * There is no strict verification here, this is to be compatible with 1574c5e512eSLei He * the unit test of the kernel. TODO: remove this until linux kernel's 1584c5e512eSLei He * unit-test is fixed. 1594c5e512eSLei He */ 1604c5e512eSLei He if (version == 1 && seq_length != 0) { 1614c5e512eSLei He if (qcrypto_der_decode_seq(&seq, &seq_length, NULL, NULL, errp) < 0) { 1624c5e512eSLei He goto error; 1634c5e512eSLei He } 1644c5e512eSLei He if (seq_length != 0) { 1654c5e512eSLei He goto error; 1664c5e512eSLei He } 1674c5e512eSLei He return rsa; 1684c5e512eSLei He } 1694c5e512eSLei He if (seq_length != 0) { 170e158f8e9SMarkus Armbruster error_setg(errp, "Invalid RSA private key"); 1714c5e512eSLei He goto error; 1724c5e512eSLei He } 1734c5e512eSLei He 1744c5e512eSLei He return rsa; 1754c5e512eSLei He 1764c5e512eSLei Heerror: 1774c5e512eSLei He qcrypto_akcipher_rsakey_free(rsa); 1784c5e512eSLei He return NULL; 1794c5e512eSLei He} 1804c5e512eSLei He 1814c5e512eSLei HeQCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse( 1824c5e512eSLei He QCryptoAkCipherKeyType type, const uint8_t *key, 1834c5e512eSLei He size_t keylen, Error **errp) 1844c5e512eSLei He{ 1854c5e512eSLei He switch (type) { 186*5f4059efSMarkus Armbruster case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE: 1874c5e512eSLei He return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp); 1884c5e512eSLei He 189*5f4059efSMarkus Armbruster case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC: 1904c5e512eSLei He return qcrypto_builtin_rsa_public_key_parse(key, keylen, errp); 1914c5e512eSLei He 1924c5e512eSLei He default: 1934c5e512eSLei He error_setg(errp, "Unknown key type: %d", type); 1944c5e512eSLei He return NULL; 1954c5e512eSLei He } 1964c5e512eSLei He} 197