1/* 2 * QEMU Crypto akcipher algorithms 3 * 4 * Copyright (c) 2022 Bytedance 5 * Author: lei he <helei.sig11@bytedance.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22#include "der.h" 23#include "rsakey.h" 24 25static int extract_mpi(void *ctx, const uint8_t *value, 26 size_t vlen, Error **errp) 27{ 28 QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx; 29 if (vlen == 0) { 30 error_setg(errp, "Empty mpi field"); 31 return -1; 32 } 33 mpi->data = g_memdup2(value, vlen); 34 mpi->len = vlen; 35 return 0; 36} 37 38static int extract_version(void *ctx, const uint8_t *value, 39 size_t vlen, Error **errp) 40{ 41 uint8_t *version = (uint8_t *)ctx; 42 if (vlen != 1 || *value > 1) { 43 error_setg(errp, "Invalid rsakey version"); 44 return -1; 45 } 46 *version = *value; 47 return 0; 48} 49 50static int extract_seq_content(void *ctx, const uint8_t *value, 51 size_t vlen, Error **errp) 52{ 53 const uint8_t **content = (const uint8_t **)ctx; 54 if (vlen == 0) { 55 error_setg(errp, "Empty sequence"); 56 return -1; 57 } 58 *content = value; 59 return 0; 60} 61 62/** 63 * 64 * RsaPubKey ::= SEQUENCE { 65 * n INTEGER 66 * e INTEGER 67 * } 68 */ 69static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_public_key_parse( 70 const uint8_t *key, size_t keylen, Error **errp) 71{ 72 QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1); 73 const uint8_t *seq; 74 size_t seq_length; 75 int decode_ret; 76 77 decode_ret = qcrypto_der_decode_seq(&key, &keylen, 78 extract_seq_content, &seq, errp); 79 if (decode_ret < 0 || keylen != 0) { 80 goto error; 81 } 82 seq_length = decode_ret; 83 84 if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 85 &rsa->n, errp) < 0 || 86 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 87 &rsa->e, errp) < 0) { 88 goto error; 89 } 90 if (seq_length != 0) { 91 goto error; 92 } 93 94 return rsa; 95 96error: 97 if (errp && !*errp) { 98 error_setg(errp, "Invalid RSA public key"); 99 } 100 qcrypto_akcipher_rsakey_free(rsa); 101 return NULL; 102} 103 104/** 105 * RsaPrivKey ::= SEQUENCE { 106 * version INTEGER 107 * n INTEGER 108 * e INTEGER 109 * d INTEGER 110 * p INTEGER 111 * q INTEGER 112 * dp INTEGER 113 * dq INTEGER 114 * u INTEGER 115 * otherPrimeInfos OtherPrimeInfos OPTIONAL 116 * } 117 */ 118static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_private_key_parse( 119 const uint8_t *key, size_t keylen, Error **errp) 120{ 121 QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1); 122 uint8_t version; 123 const uint8_t *seq; 124 int decode_ret; 125 size_t seq_length; 126 127 decode_ret = qcrypto_der_decode_seq(&key, &keylen, extract_seq_content, 128 &seq, errp); 129 if (decode_ret < 0 || keylen != 0) { 130 goto error; 131 } 132 seq_length = decode_ret; 133 134 decode_ret = qcrypto_der_decode_int(&seq, &seq_length, extract_version, 135 &version, errp); 136 137 if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 138 &rsa->n, errp) < 0 || 139 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 140 &rsa->e, errp) < 0 || 141 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, 142 &rsa->d, errp) < 0 || 143 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->p, 144 errp) < 0 || 145 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->q, 146 errp) < 0 || 147 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dp, 148 errp) < 0 || 149 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dq, 150 errp) < 0 || 151 qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->u, 152 errp) < 0) { 153 goto error; 154 } 155 156 /** 157 * According to the standard, otherPrimeInfos must be present for version 1. 158 * There is no strict verification here, this is to be compatible with 159 * the unit test of the kernel. TODO: remove this until linux kernel's 160 * unit-test is fixed. 161 */ 162 if (version == 1 && seq_length != 0) { 163 if (qcrypto_der_decode_seq(&seq, &seq_length, NULL, NULL, errp) < 0) { 164 goto error; 165 } 166 if (seq_length != 0) { 167 goto error; 168 } 169 return rsa; 170 } 171 if (seq_length != 0) { 172 goto error; 173 } 174 175 return rsa; 176 177error: 178 if (errp && !*errp) { 179 error_setg(errp, "Invalid RSA private key"); 180 } 181 qcrypto_akcipher_rsakey_free(rsa); 182 return NULL; 183} 184 185QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse( 186 QCryptoAkCipherKeyType type, const uint8_t *key, 187 size_t keylen, Error **errp) 188{ 189 switch (type) { 190 case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE: 191 return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp); 192 193 case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC: 194 return qcrypto_builtin_rsa_public_key_parse(key, keylen, errp); 195 196 default: 197 error_setg(errp, "Unknown key type: %d", type); 198 return NULL; 199 } 200} 201