Webserver+3d print
cyclone_crypto/rsa.c@0:8918a71cdbe9, 2017-02-04 (annotated)
- Committer:
- Sergunb
- Date:
- Sat Feb 04 18:15:49 2017 +0000
- Revision:
- 0:8918a71cdbe9
nothing else
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Sergunb | 0:8918a71cdbe9 | 1 | /** |
Sergunb | 0:8918a71cdbe9 | 2 | * @file rsa.c |
Sergunb | 0:8918a71cdbe9 | 3 | * @brief RSA public-key cryptography standard |
Sergunb | 0:8918a71cdbe9 | 4 | * |
Sergunb | 0:8918a71cdbe9 | 5 | * @section License |
Sergunb | 0:8918a71cdbe9 | 6 | * |
Sergunb | 0:8918a71cdbe9 | 7 | * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. |
Sergunb | 0:8918a71cdbe9 | 8 | * |
Sergunb | 0:8918a71cdbe9 | 9 | * This file is part of CycloneCrypto Open. |
Sergunb | 0:8918a71cdbe9 | 10 | * |
Sergunb | 0:8918a71cdbe9 | 11 | * This program is free software; you can redistribute it and/or |
Sergunb | 0:8918a71cdbe9 | 12 | * modify it under the terms of the GNU General Public License |
Sergunb | 0:8918a71cdbe9 | 13 | * as published by the Free Software Foundation; either version 2 |
Sergunb | 0:8918a71cdbe9 | 14 | * of the License, or (at your option) any later version. |
Sergunb | 0:8918a71cdbe9 | 15 | * |
Sergunb | 0:8918a71cdbe9 | 16 | * This program is distributed in the hope that it will be useful, |
Sergunb | 0:8918a71cdbe9 | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
Sergunb | 0:8918a71cdbe9 | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Sergunb | 0:8918a71cdbe9 | 19 | * GNU General Public License for more details. |
Sergunb | 0:8918a71cdbe9 | 20 | * |
Sergunb | 0:8918a71cdbe9 | 21 | * You should have received a copy of the GNU General Public License |
Sergunb | 0:8918a71cdbe9 | 22 | * along with this program; if not, write to the Free Software Foundation, |
Sergunb | 0:8918a71cdbe9 | 23 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
Sergunb | 0:8918a71cdbe9 | 24 | * |
Sergunb | 0:8918a71cdbe9 | 25 | * @section Description |
Sergunb | 0:8918a71cdbe9 | 26 | * |
Sergunb | 0:8918a71cdbe9 | 27 | * RSA is an algorithm for public-key cryptography which is suitable for signing |
Sergunb | 0:8918a71cdbe9 | 28 | * as well as encryption. Refer to PKCS #1 (RSA Cryptography Standard) |
Sergunb | 0:8918a71cdbe9 | 29 | * |
Sergunb | 0:8918a71cdbe9 | 30 | * @author Oryx Embedded SARL (www.oryx-embedded.com) |
Sergunb | 0:8918a71cdbe9 | 31 | * @version 1.7.6 |
Sergunb | 0:8918a71cdbe9 | 32 | **/ |
Sergunb | 0:8918a71cdbe9 | 33 | |
Sergunb | 0:8918a71cdbe9 | 34 | //Switch to the appropriate trace level |
Sergunb | 0:8918a71cdbe9 | 35 | #define TRACE_LEVEL CRYPTO_TRACE_LEVEL |
Sergunb | 0:8918a71cdbe9 | 36 | |
Sergunb | 0:8918a71cdbe9 | 37 | //Dependencies |
Sergunb | 0:8918a71cdbe9 | 38 | #include <stdlib.h> |
Sergunb | 0:8918a71cdbe9 | 39 | #include <string.h> |
Sergunb | 0:8918a71cdbe9 | 40 | #include "crypto.h" |
Sergunb | 0:8918a71cdbe9 | 41 | #include "rsa.h" |
Sergunb | 0:8918a71cdbe9 | 42 | #include "mpi.h" |
Sergunb | 0:8918a71cdbe9 | 43 | #include "asn1.h" |
Sergunb | 0:8918a71cdbe9 | 44 | #include "oid.h" |
Sergunb | 0:8918a71cdbe9 | 45 | #include "debug.h" |
Sergunb | 0:8918a71cdbe9 | 46 | |
Sergunb | 0:8918a71cdbe9 | 47 | //Check crypto library configuration |
Sergunb | 0:8918a71cdbe9 | 48 | #if (RSA_SUPPORT == ENABLED) |
Sergunb | 0:8918a71cdbe9 | 49 | |
Sergunb | 0:8918a71cdbe9 | 50 | //PKCS #1 OID (1.2.840.113549.1.1) |
Sergunb | 0:8918a71cdbe9 | 51 | const uint8_t PKCS1_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01}; |
Sergunb | 0:8918a71cdbe9 | 52 | //RSA encryption OID (1.2.840.113549.1.1.1) |
Sergunb | 0:8918a71cdbe9 | 53 | const uint8_t RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01}; |
Sergunb | 0:8918a71cdbe9 | 54 | //MD5 with RSA encryption OID (1.2.840.113549.1.1.4) |
Sergunb | 0:8918a71cdbe9 | 55 | const uint8_t MD5_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04}; |
Sergunb | 0:8918a71cdbe9 | 56 | //SHA-1 with RSA encryption OID (1.2.840.113549.1.1.5) |
Sergunb | 0:8918a71cdbe9 | 57 | const uint8_t SHA1_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05}; |
Sergunb | 0:8918a71cdbe9 | 58 | //SHA-256 with RSA encryption OID (1.2.840.113549.1.1.11) |
Sergunb | 0:8918a71cdbe9 | 59 | const uint8_t SHA256_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B}; |
Sergunb | 0:8918a71cdbe9 | 60 | //SHA-384 with RSA encryption OID (1.2.840.113549.1.1.12) |
Sergunb | 0:8918a71cdbe9 | 61 | const uint8_t SHA384_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C}; |
Sergunb | 0:8918a71cdbe9 | 62 | //SHA-512 with RSA encryption OID (1.2.840.113549.1.1.13) |
Sergunb | 0:8918a71cdbe9 | 63 | const uint8_t SHA512_WITH_RSA_ENCRYPTION_OID[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D}; |
Sergunb | 0:8918a71cdbe9 | 64 | //RSA PKCS #1 v1.5 signature with SHA-3-224 OID (2.16.840.1.101.3.4.3.13) |
Sergunb | 0:8918a71cdbe9 | 65 | const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0D}; |
Sergunb | 0:8918a71cdbe9 | 66 | //RSA PKCS #1 v1.5 signature with SHA-3-256 OID (2.16.840.1.101.3.4.3.14) |
Sergunb | 0:8918a71cdbe9 | 67 | const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0E}; |
Sergunb | 0:8918a71cdbe9 | 68 | //RSA PKCS #1 v1.5 signature with SHA-3-384 OID (2.16.840.1.101.3.4.3.15) |
Sergunb | 0:8918a71cdbe9 | 69 | const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0F}; |
Sergunb | 0:8918a71cdbe9 | 70 | //RSA PKCS #1 v1.5 signature with SHA-3-512 OID (2.16.840.1.101.3.4.3.16) |
Sergunb | 0:8918a71cdbe9 | 71 | const uint8_t RSASSA_PKCS1_v1_5_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x10}; |
Sergunb | 0:8918a71cdbe9 | 72 | |
Sergunb | 0:8918a71cdbe9 | 73 | |
Sergunb | 0:8918a71cdbe9 | 74 | /** |
Sergunb | 0:8918a71cdbe9 | 75 | * @brief Initialize a RSA public key |
Sergunb | 0:8918a71cdbe9 | 76 | * @param[in] key Pointer to the RSA public key to initialize |
Sergunb | 0:8918a71cdbe9 | 77 | **/ |
Sergunb | 0:8918a71cdbe9 | 78 | |
Sergunb | 0:8918a71cdbe9 | 79 | void rsaInitPublicKey(RsaPublicKey *key) |
Sergunb | 0:8918a71cdbe9 | 80 | { |
Sergunb | 0:8918a71cdbe9 | 81 | //Initialize multiple precision integers |
Sergunb | 0:8918a71cdbe9 | 82 | mpiInit(&key->n); |
Sergunb | 0:8918a71cdbe9 | 83 | mpiInit(&key->e); |
Sergunb | 0:8918a71cdbe9 | 84 | } |
Sergunb | 0:8918a71cdbe9 | 85 | |
Sergunb | 0:8918a71cdbe9 | 86 | |
Sergunb | 0:8918a71cdbe9 | 87 | /** |
Sergunb | 0:8918a71cdbe9 | 88 | * @brief Release a RSA public key |
Sergunb | 0:8918a71cdbe9 | 89 | * @param[in] key Pointer to the RSA public key to free |
Sergunb | 0:8918a71cdbe9 | 90 | **/ |
Sergunb | 0:8918a71cdbe9 | 91 | |
Sergunb | 0:8918a71cdbe9 | 92 | void rsaFreePublicKey(RsaPublicKey *key) |
Sergunb | 0:8918a71cdbe9 | 93 | { |
Sergunb | 0:8918a71cdbe9 | 94 | //Free multiple precision integers |
Sergunb | 0:8918a71cdbe9 | 95 | mpiFree(&key->n); |
Sergunb | 0:8918a71cdbe9 | 96 | mpiFree(&key->e); |
Sergunb | 0:8918a71cdbe9 | 97 | } |
Sergunb | 0:8918a71cdbe9 | 98 | |
Sergunb | 0:8918a71cdbe9 | 99 | |
Sergunb | 0:8918a71cdbe9 | 100 | /** |
Sergunb | 0:8918a71cdbe9 | 101 | * @brief Initialize a RSA private key |
Sergunb | 0:8918a71cdbe9 | 102 | * @param[in] key Pointer to the RSA private key to initialize |
Sergunb | 0:8918a71cdbe9 | 103 | **/ |
Sergunb | 0:8918a71cdbe9 | 104 | |
Sergunb | 0:8918a71cdbe9 | 105 | void rsaInitPrivateKey(RsaPrivateKey *key) |
Sergunb | 0:8918a71cdbe9 | 106 | { |
Sergunb | 0:8918a71cdbe9 | 107 | //Initialize multiple precision integers |
Sergunb | 0:8918a71cdbe9 | 108 | mpiInit(&key->n); |
Sergunb | 0:8918a71cdbe9 | 109 | mpiInit(&key->e); |
Sergunb | 0:8918a71cdbe9 | 110 | mpiInit(&key->d); |
Sergunb | 0:8918a71cdbe9 | 111 | mpiInit(&key->p); |
Sergunb | 0:8918a71cdbe9 | 112 | mpiInit(&key->q); |
Sergunb | 0:8918a71cdbe9 | 113 | mpiInit(&key->dp); |
Sergunb | 0:8918a71cdbe9 | 114 | mpiInit(&key->dq); |
Sergunb | 0:8918a71cdbe9 | 115 | mpiInit(&key->qinv); |
Sergunb | 0:8918a71cdbe9 | 116 | } |
Sergunb | 0:8918a71cdbe9 | 117 | |
Sergunb | 0:8918a71cdbe9 | 118 | |
Sergunb | 0:8918a71cdbe9 | 119 | /** |
Sergunb | 0:8918a71cdbe9 | 120 | * @brief Release a RSA private key |
Sergunb | 0:8918a71cdbe9 | 121 | * @param[in] key Pointer to the RSA private key to free |
Sergunb | 0:8918a71cdbe9 | 122 | **/ |
Sergunb | 0:8918a71cdbe9 | 123 | |
Sergunb | 0:8918a71cdbe9 | 124 | void rsaFreePrivateKey(RsaPrivateKey *key) |
Sergunb | 0:8918a71cdbe9 | 125 | { |
Sergunb | 0:8918a71cdbe9 | 126 | //Free multiple precision integers |
Sergunb | 0:8918a71cdbe9 | 127 | mpiFree(&key->n); |
Sergunb | 0:8918a71cdbe9 | 128 | mpiFree(&key->e); |
Sergunb | 0:8918a71cdbe9 | 129 | mpiFree(&key->d); |
Sergunb | 0:8918a71cdbe9 | 130 | mpiFree(&key->p); |
Sergunb | 0:8918a71cdbe9 | 131 | mpiFree(&key->q); |
Sergunb | 0:8918a71cdbe9 | 132 | mpiFree(&key->dp); |
Sergunb | 0:8918a71cdbe9 | 133 | mpiFree(&key->dq); |
Sergunb | 0:8918a71cdbe9 | 134 | mpiFree(&key->qinv); |
Sergunb | 0:8918a71cdbe9 | 135 | } |
Sergunb | 0:8918a71cdbe9 | 136 | |
Sergunb | 0:8918a71cdbe9 | 137 | |
Sergunb | 0:8918a71cdbe9 | 138 | /** |
Sergunb | 0:8918a71cdbe9 | 139 | * @brief RSA encryption primitive |
Sergunb | 0:8918a71cdbe9 | 140 | * |
Sergunb | 0:8918a71cdbe9 | 141 | * The RSA encryption primitive produces a ciphertext representative from |
Sergunb | 0:8918a71cdbe9 | 142 | * a message representative under the control of a public key |
Sergunb | 0:8918a71cdbe9 | 143 | * |
Sergunb | 0:8918a71cdbe9 | 144 | * @param[in] key RSA public key |
Sergunb | 0:8918a71cdbe9 | 145 | * @param[in] m Message representative |
Sergunb | 0:8918a71cdbe9 | 146 | * @param[out] c Ciphertext representative |
Sergunb | 0:8918a71cdbe9 | 147 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 148 | **/ |
Sergunb | 0:8918a71cdbe9 | 149 | |
Sergunb | 0:8918a71cdbe9 | 150 | error_t rsaep(const RsaPublicKey *key, const Mpi *m, Mpi *c) |
Sergunb | 0:8918a71cdbe9 | 151 | { |
Sergunb | 0:8918a71cdbe9 | 152 | //Ensure the RSA public key is valid |
Sergunb | 0:8918a71cdbe9 | 153 | if(!key->n.size || !key->e.size) |
Sergunb | 0:8918a71cdbe9 | 154 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 155 | |
Sergunb | 0:8918a71cdbe9 | 156 | //The message representative m shall be between 0 and n - 1 |
Sergunb | 0:8918a71cdbe9 | 157 | if(mpiCompInt(m, 0) < 0 || mpiComp(m, &key->n) >= 0) |
Sergunb | 0:8918a71cdbe9 | 158 | return ERROR_OUT_OF_RANGE; |
Sergunb | 0:8918a71cdbe9 | 159 | |
Sergunb | 0:8918a71cdbe9 | 160 | //Perform modular exponentiation (c = m ^ e mod n) |
Sergunb | 0:8918a71cdbe9 | 161 | return mpiExpMod(c, m, &key->e, &key->n); |
Sergunb | 0:8918a71cdbe9 | 162 | } |
Sergunb | 0:8918a71cdbe9 | 163 | |
Sergunb | 0:8918a71cdbe9 | 164 | |
Sergunb | 0:8918a71cdbe9 | 165 | /** |
Sergunb | 0:8918a71cdbe9 | 166 | * @brief RSA decryption primitive |
Sergunb | 0:8918a71cdbe9 | 167 | * |
Sergunb | 0:8918a71cdbe9 | 168 | * The RSA decryption primitive recovers the message representative from |
Sergunb | 0:8918a71cdbe9 | 169 | * the ciphertext representative under the control of a private key |
Sergunb | 0:8918a71cdbe9 | 170 | * |
Sergunb | 0:8918a71cdbe9 | 171 | * @param[in] key RSA private key |
Sergunb | 0:8918a71cdbe9 | 172 | * @param[in] c Ciphertext representative |
Sergunb | 0:8918a71cdbe9 | 173 | * @param[out] m Message representative |
Sergunb | 0:8918a71cdbe9 | 174 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 175 | **/ |
Sergunb | 0:8918a71cdbe9 | 176 | |
Sergunb | 0:8918a71cdbe9 | 177 | error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m) |
Sergunb | 0:8918a71cdbe9 | 178 | { |
Sergunb | 0:8918a71cdbe9 | 179 | error_t error; |
Sergunb | 0:8918a71cdbe9 | 180 | Mpi m1; |
Sergunb | 0:8918a71cdbe9 | 181 | Mpi m2; |
Sergunb | 0:8918a71cdbe9 | 182 | Mpi h; |
Sergunb | 0:8918a71cdbe9 | 183 | |
Sergunb | 0:8918a71cdbe9 | 184 | //The ciphertext representative c shall be between 0 and n - 1 |
Sergunb | 0:8918a71cdbe9 | 185 | if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0) |
Sergunb | 0:8918a71cdbe9 | 186 | return ERROR_OUT_OF_RANGE; |
Sergunb | 0:8918a71cdbe9 | 187 | |
Sergunb | 0:8918a71cdbe9 | 188 | //Initialize multiple-precision integers |
Sergunb | 0:8918a71cdbe9 | 189 | mpiInit(&m1); |
Sergunb | 0:8918a71cdbe9 | 190 | mpiInit(&m2); |
Sergunb | 0:8918a71cdbe9 | 191 | mpiInit(&h); |
Sergunb | 0:8918a71cdbe9 | 192 | |
Sergunb | 0:8918a71cdbe9 | 193 | //Use the Chinese remainder algorithm? |
Sergunb | 0:8918a71cdbe9 | 194 | if(key->n.size && key->p.size && key->q.size && |
Sergunb | 0:8918a71cdbe9 | 195 | key->dp.size && key->dq.size && key->qinv.size) |
Sergunb | 0:8918a71cdbe9 | 196 | { |
Sergunb | 0:8918a71cdbe9 | 197 | //Compute m1 = c ^ dP mod p |
Sergunb | 0:8918a71cdbe9 | 198 | MPI_CHECK(mpiExpMod(&m1, c, &key->dp, &key->p)); |
Sergunb | 0:8918a71cdbe9 | 199 | //Compute m2 = c ^ dQ mod q |
Sergunb | 0:8918a71cdbe9 | 200 | MPI_CHECK(mpiExpMod(&m2, c, &key->dq, &key->q)); |
Sergunb | 0:8918a71cdbe9 | 201 | //Let h = (m1 - m2) * qInv mod p |
Sergunb | 0:8918a71cdbe9 | 202 | MPI_CHECK(mpiSub(&h, &m1, &m2)); |
Sergunb | 0:8918a71cdbe9 | 203 | MPI_CHECK(mpiMulMod(&h, &h, &key->qinv, &key->p)); |
Sergunb | 0:8918a71cdbe9 | 204 | //Let m = m2 + q * h |
Sergunb | 0:8918a71cdbe9 | 205 | MPI_CHECK(mpiMul(m, &key->q, &h)); |
Sergunb | 0:8918a71cdbe9 | 206 | MPI_CHECK(mpiAdd(m, m, &m2)); |
Sergunb | 0:8918a71cdbe9 | 207 | } |
Sergunb | 0:8918a71cdbe9 | 208 | //Use modular exponentiation? |
Sergunb | 0:8918a71cdbe9 | 209 | else if(key->n.size && key->d.size) |
Sergunb | 0:8918a71cdbe9 | 210 | { |
Sergunb | 0:8918a71cdbe9 | 211 | //Let m = c ^ d mod n |
Sergunb | 0:8918a71cdbe9 | 212 | error = mpiExpMod(m, c, &key->d, &key->n); |
Sergunb | 0:8918a71cdbe9 | 213 | } |
Sergunb | 0:8918a71cdbe9 | 214 | //Invalid parameters? |
Sergunb | 0:8918a71cdbe9 | 215 | else |
Sergunb | 0:8918a71cdbe9 | 216 | { |
Sergunb | 0:8918a71cdbe9 | 217 | //Report an error |
Sergunb | 0:8918a71cdbe9 | 218 | error = ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 219 | } |
Sergunb | 0:8918a71cdbe9 | 220 | |
Sergunb | 0:8918a71cdbe9 | 221 | end: |
Sergunb | 0:8918a71cdbe9 | 222 | //Free previously allocated memory |
Sergunb | 0:8918a71cdbe9 | 223 | mpiFree(&m1); |
Sergunb | 0:8918a71cdbe9 | 224 | mpiFree(&m2); |
Sergunb | 0:8918a71cdbe9 | 225 | mpiFree(&h); |
Sergunb | 0:8918a71cdbe9 | 226 | |
Sergunb | 0:8918a71cdbe9 | 227 | //Return status code |
Sergunb | 0:8918a71cdbe9 | 228 | return error; |
Sergunb | 0:8918a71cdbe9 | 229 | } |
Sergunb | 0:8918a71cdbe9 | 230 | |
Sergunb | 0:8918a71cdbe9 | 231 | |
Sergunb | 0:8918a71cdbe9 | 232 | /** |
Sergunb | 0:8918a71cdbe9 | 233 | * @brief RSA signature primitive |
Sergunb | 0:8918a71cdbe9 | 234 | * |
Sergunb | 0:8918a71cdbe9 | 235 | * The RSA signature primitive produces a signature representative from |
Sergunb | 0:8918a71cdbe9 | 236 | * a message representative under the control of a private key |
Sergunb | 0:8918a71cdbe9 | 237 | * |
Sergunb | 0:8918a71cdbe9 | 238 | * @param[in] key RSA private key |
Sergunb | 0:8918a71cdbe9 | 239 | * @param[in] m Message representative |
Sergunb | 0:8918a71cdbe9 | 240 | * @param[out] s Signature representative |
Sergunb | 0:8918a71cdbe9 | 241 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 242 | **/ |
Sergunb | 0:8918a71cdbe9 | 243 | |
Sergunb | 0:8918a71cdbe9 | 244 | error_t rsasp1(const RsaPrivateKey *key, const Mpi *m, Mpi *s) |
Sergunb | 0:8918a71cdbe9 | 245 | { |
Sergunb | 0:8918a71cdbe9 | 246 | //RSASP1 primitive is the same as RSADP except for the names of its |
Sergunb | 0:8918a71cdbe9 | 247 | //input and output arguments. They are distinguished as they are |
Sergunb | 0:8918a71cdbe9 | 248 | //intended for different purposes |
Sergunb | 0:8918a71cdbe9 | 249 | return rsadp(key, m, s); |
Sergunb | 0:8918a71cdbe9 | 250 | } |
Sergunb | 0:8918a71cdbe9 | 251 | |
Sergunb | 0:8918a71cdbe9 | 252 | |
Sergunb | 0:8918a71cdbe9 | 253 | /** |
Sergunb | 0:8918a71cdbe9 | 254 | * @brief RSA verification primitive |
Sergunb | 0:8918a71cdbe9 | 255 | * |
Sergunb | 0:8918a71cdbe9 | 256 | * The RSA verification primitive recovers the message representative from |
Sergunb | 0:8918a71cdbe9 | 257 | * the signature representative under the control of a public key |
Sergunb | 0:8918a71cdbe9 | 258 | * |
Sergunb | 0:8918a71cdbe9 | 259 | * @param[in] key RSA public key |
Sergunb | 0:8918a71cdbe9 | 260 | * @param[in] s Signature representative |
Sergunb | 0:8918a71cdbe9 | 261 | * @param[out] m Message representative |
Sergunb | 0:8918a71cdbe9 | 262 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 263 | **/ |
Sergunb | 0:8918a71cdbe9 | 264 | |
Sergunb | 0:8918a71cdbe9 | 265 | error_t rsavp1(const RsaPublicKey *key, const Mpi *s, Mpi *m) |
Sergunb | 0:8918a71cdbe9 | 266 | { |
Sergunb | 0:8918a71cdbe9 | 267 | //RSAVP1 primitive is the same as RSAEP except for the names of its |
Sergunb | 0:8918a71cdbe9 | 268 | //input and output arguments. They are distinguished as they are |
Sergunb | 0:8918a71cdbe9 | 269 | //intended for different purposes |
Sergunb | 0:8918a71cdbe9 | 270 | return rsaep(key, s, m); |
Sergunb | 0:8918a71cdbe9 | 271 | } |
Sergunb | 0:8918a71cdbe9 | 272 | |
Sergunb | 0:8918a71cdbe9 | 273 | |
Sergunb | 0:8918a71cdbe9 | 274 | /** |
Sergunb | 0:8918a71cdbe9 | 275 | * @brief PKCS #1 v1.5 encryption operation |
Sergunb | 0:8918a71cdbe9 | 276 | * @param[in] prngAlgo PRNG algorithm |
Sergunb | 0:8918a71cdbe9 | 277 | * @param[in] prngContext Pointer to the PRNG context |
Sergunb | 0:8918a71cdbe9 | 278 | * @param[in] key Recipient's RSA public key |
Sergunb | 0:8918a71cdbe9 | 279 | * @param[in] message Message to be encrypted |
Sergunb | 0:8918a71cdbe9 | 280 | * @param[in] messageLength Length of the message to be encrypted |
Sergunb | 0:8918a71cdbe9 | 281 | * @param[out] ciphertext Ciphertext resulting from the encryption operation |
Sergunb | 0:8918a71cdbe9 | 282 | * @param[out] ciphertextLength Length of the resulting ciphertext |
Sergunb | 0:8918a71cdbe9 | 283 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 284 | **/ |
Sergunb | 0:8918a71cdbe9 | 285 | |
Sergunb | 0:8918a71cdbe9 | 286 | error_t rsaesPkcs1v15Encrypt(const PrngAlgo *prngAlgo, void *prngContext, const RsaPublicKey *key, |
Sergunb | 0:8918a71cdbe9 | 287 | const uint8_t *message, size_t messageLength, uint8_t *ciphertext, size_t *ciphertextLength) |
Sergunb | 0:8918a71cdbe9 | 288 | { |
Sergunb | 0:8918a71cdbe9 | 289 | error_t error; |
Sergunb | 0:8918a71cdbe9 | 290 | uint_t i; |
Sergunb | 0:8918a71cdbe9 | 291 | uint_t j; |
Sergunb | 0:8918a71cdbe9 | 292 | uint_t k; |
Sergunb | 0:8918a71cdbe9 | 293 | uint_t n; |
Sergunb | 0:8918a71cdbe9 | 294 | uint8_t *p; |
Sergunb | 0:8918a71cdbe9 | 295 | Mpi m; |
Sergunb | 0:8918a71cdbe9 | 296 | Mpi c; |
Sergunb | 0:8918a71cdbe9 | 297 | |
Sergunb | 0:8918a71cdbe9 | 298 | //Check parameters |
Sergunb | 0:8918a71cdbe9 | 299 | if(key == NULL || message == NULL) |
Sergunb | 0:8918a71cdbe9 | 300 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 301 | if(ciphertext == NULL || ciphertextLength == NULL) |
Sergunb | 0:8918a71cdbe9 | 302 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 303 | |
Sergunb | 0:8918a71cdbe9 | 304 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 305 | TRACE_DEBUG("RSA PKCS #1 v1.5 encryption...\r\n"); |
Sergunb | 0:8918a71cdbe9 | 306 | TRACE_DEBUG(" Modulus:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 307 | TRACE_DEBUG_MPI(" ", &key->n); |
Sergunb | 0:8918a71cdbe9 | 308 | TRACE_DEBUG(" Public exponent:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 309 | TRACE_DEBUG_MPI(" ", &key->e); |
Sergunb | 0:8918a71cdbe9 | 310 | TRACE_DEBUG(" Message:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 311 | TRACE_DEBUG_ARRAY(" ", message, messageLength); |
Sergunb | 0:8918a71cdbe9 | 312 | |
Sergunb | 0:8918a71cdbe9 | 313 | //Initialize multiple-precision integers |
Sergunb | 0:8918a71cdbe9 | 314 | mpiInit(&m); |
Sergunb | 0:8918a71cdbe9 | 315 | mpiInit(&c); |
Sergunb | 0:8918a71cdbe9 | 316 | |
Sergunb | 0:8918a71cdbe9 | 317 | //Get the length in octets of the modulus n |
Sergunb | 0:8918a71cdbe9 | 318 | k = mpiGetByteLength(&key->n); |
Sergunb | 0:8918a71cdbe9 | 319 | |
Sergunb | 0:8918a71cdbe9 | 320 | //Check the length of the message |
Sergunb | 0:8918a71cdbe9 | 321 | if((messageLength + 11) > k) |
Sergunb | 0:8918a71cdbe9 | 322 | return ERROR_INVALID_LENGTH; |
Sergunb | 0:8918a71cdbe9 | 323 | |
Sergunb | 0:8918a71cdbe9 | 324 | //Point to the buffer where the encoded message EM will be formatted |
Sergunb | 0:8918a71cdbe9 | 325 | p = ciphertext; |
Sergunb | 0:8918a71cdbe9 | 326 | |
Sergunb | 0:8918a71cdbe9 | 327 | //The leading 0x00 octet ensures that the encoded message, |
Sergunb | 0:8918a71cdbe9 | 328 | //converted to an integer, is less than the modulus |
Sergunb | 0:8918a71cdbe9 | 329 | *(p++) = 0x00; |
Sergunb | 0:8918a71cdbe9 | 330 | //For a public-key operation, the block type BT shall be 0x02 |
Sergunb | 0:8918a71cdbe9 | 331 | *(p++) = 0x02; |
Sergunb | 0:8918a71cdbe9 | 332 | |
Sergunb | 0:8918a71cdbe9 | 333 | //Length of the padding string PS |
Sergunb | 0:8918a71cdbe9 | 334 | n = k - messageLength - 3; |
Sergunb | 0:8918a71cdbe9 | 335 | |
Sergunb | 0:8918a71cdbe9 | 336 | //Generate the padding string (pseudo-randomly generated non-zero octets) |
Sergunb | 0:8918a71cdbe9 | 337 | while(n > 0) |
Sergunb | 0:8918a71cdbe9 | 338 | { |
Sergunb | 0:8918a71cdbe9 | 339 | //Generate random data |
Sergunb | 0:8918a71cdbe9 | 340 | error = prngAlgo->read(prngContext, p, n); |
Sergunb | 0:8918a71cdbe9 | 341 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 342 | if(error) |
Sergunb | 0:8918a71cdbe9 | 343 | return error; |
Sergunb | 0:8918a71cdbe9 | 344 | |
Sergunb | 0:8918a71cdbe9 | 345 | //Parse the resulting octet string |
Sergunb | 0:8918a71cdbe9 | 346 | for(i = 0, j = 0; j < n; j++) |
Sergunb | 0:8918a71cdbe9 | 347 | { |
Sergunb | 0:8918a71cdbe9 | 348 | //Strip any byte with a value of zero |
Sergunb | 0:8918a71cdbe9 | 349 | if(p[j] != 0) |
Sergunb | 0:8918a71cdbe9 | 350 | p[i++] = p[j]; |
Sergunb | 0:8918a71cdbe9 | 351 | } |
Sergunb | 0:8918a71cdbe9 | 352 | |
Sergunb | 0:8918a71cdbe9 | 353 | //Advance data pointer |
Sergunb | 0:8918a71cdbe9 | 354 | p += i; |
Sergunb | 0:8918a71cdbe9 | 355 | n -= i; |
Sergunb | 0:8918a71cdbe9 | 356 | } |
Sergunb | 0:8918a71cdbe9 | 357 | |
Sergunb | 0:8918a71cdbe9 | 358 | //Append a 0x00 octet to the padding string |
Sergunb | 0:8918a71cdbe9 | 359 | *(p++) = 0x00; |
Sergunb | 0:8918a71cdbe9 | 360 | //Copy the message to be encrypted |
Sergunb | 0:8918a71cdbe9 | 361 | memcpy(p, message, messageLength); |
Sergunb | 0:8918a71cdbe9 | 362 | |
Sergunb | 0:8918a71cdbe9 | 363 | //Rewind to the beginning of the encoded message |
Sergunb | 0:8918a71cdbe9 | 364 | p = ciphertext; |
Sergunb | 0:8918a71cdbe9 | 365 | |
Sergunb | 0:8918a71cdbe9 | 366 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 367 | TRACE_DEBUG(" Encoded message\r\n"); |
Sergunb | 0:8918a71cdbe9 | 368 | TRACE_DEBUG_ARRAY(" ", p, k); |
Sergunb | 0:8918a71cdbe9 | 369 | |
Sergunb | 0:8918a71cdbe9 | 370 | //Start of exception handling block |
Sergunb | 0:8918a71cdbe9 | 371 | do |
Sergunb | 0:8918a71cdbe9 | 372 | { |
Sergunb | 0:8918a71cdbe9 | 373 | //Convert the encoded message EM to an integer message representative m |
Sergunb | 0:8918a71cdbe9 | 374 | error = mpiReadRaw(&m, p, k); |
Sergunb | 0:8918a71cdbe9 | 375 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 376 | if(error) |
Sergunb | 0:8918a71cdbe9 | 377 | break; |
Sergunb | 0:8918a71cdbe9 | 378 | |
Sergunb | 0:8918a71cdbe9 | 379 | //Apply the RSAEP encryption primitive |
Sergunb | 0:8918a71cdbe9 | 380 | error = rsaep(key, &m, &c); |
Sergunb | 0:8918a71cdbe9 | 381 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 382 | if(error) |
Sergunb | 0:8918a71cdbe9 | 383 | break; |
Sergunb | 0:8918a71cdbe9 | 384 | |
Sergunb | 0:8918a71cdbe9 | 385 | //Convert the ciphertext representative c to a ciphertext of length k octets |
Sergunb | 0:8918a71cdbe9 | 386 | error = mpiWriteRaw(&c, ciphertext, k); |
Sergunb | 0:8918a71cdbe9 | 387 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 388 | if(error) |
Sergunb | 0:8918a71cdbe9 | 389 | break; |
Sergunb | 0:8918a71cdbe9 | 390 | |
Sergunb | 0:8918a71cdbe9 | 391 | //Length of the resulting ciphertext |
Sergunb | 0:8918a71cdbe9 | 392 | *ciphertextLength = k; |
Sergunb | 0:8918a71cdbe9 | 393 | |
Sergunb | 0:8918a71cdbe9 | 394 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 395 | TRACE_DEBUG(" Ciphertext:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 396 | TRACE_DEBUG_ARRAY(" ", ciphertext, *ciphertextLength); |
Sergunb | 0:8918a71cdbe9 | 397 | |
Sergunb | 0:8918a71cdbe9 | 398 | //End of exception handling block |
Sergunb | 0:8918a71cdbe9 | 399 | } while(0); |
Sergunb | 0:8918a71cdbe9 | 400 | |
Sergunb | 0:8918a71cdbe9 | 401 | //Free previously allocated memory |
Sergunb | 0:8918a71cdbe9 | 402 | mpiFree(&m); |
Sergunb | 0:8918a71cdbe9 | 403 | mpiFree(&c); |
Sergunb | 0:8918a71cdbe9 | 404 | |
Sergunb | 0:8918a71cdbe9 | 405 | //Return status code |
Sergunb | 0:8918a71cdbe9 | 406 | return error; |
Sergunb | 0:8918a71cdbe9 | 407 | } |
Sergunb | 0:8918a71cdbe9 | 408 | |
Sergunb | 0:8918a71cdbe9 | 409 | |
Sergunb | 0:8918a71cdbe9 | 410 | /** |
Sergunb | 0:8918a71cdbe9 | 411 | * @brief PKCS #1 v1.5 decryption operation |
Sergunb | 0:8918a71cdbe9 | 412 | * @param[in] key Recipient's RSA private key |
Sergunb | 0:8918a71cdbe9 | 413 | * @param[in] ciphertext Ciphertext to be decrypted |
Sergunb | 0:8918a71cdbe9 | 414 | * @param[in] ciphertextLength Length of the ciphertext to be decrypted |
Sergunb | 0:8918a71cdbe9 | 415 | * @param[out] message Output buffer where to store the decrypted message |
Sergunb | 0:8918a71cdbe9 | 416 | * @param[in] messageSize Size of the output buffer |
Sergunb | 0:8918a71cdbe9 | 417 | * @param[out] messageLength Length of the decrypted message |
Sergunb | 0:8918a71cdbe9 | 418 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 419 | **/ |
Sergunb | 0:8918a71cdbe9 | 420 | |
Sergunb | 0:8918a71cdbe9 | 421 | error_t rsaesPkcs1v15Decrypt(const RsaPrivateKey *key, const uint8_t *ciphertext, |
Sergunb | 0:8918a71cdbe9 | 422 | size_t ciphertextLength, uint8_t *message, size_t messageSize, size_t *messageLength) |
Sergunb | 0:8918a71cdbe9 | 423 | { |
Sergunb | 0:8918a71cdbe9 | 424 | error_t error; |
Sergunb | 0:8918a71cdbe9 | 425 | uint_t i; |
Sergunb | 0:8918a71cdbe9 | 426 | uint_t k; |
Sergunb | 0:8918a71cdbe9 | 427 | uint8_t *em; |
Sergunb | 0:8918a71cdbe9 | 428 | Mpi c; |
Sergunb | 0:8918a71cdbe9 | 429 | Mpi m; |
Sergunb | 0:8918a71cdbe9 | 430 | |
Sergunb | 0:8918a71cdbe9 | 431 | //Check parameters |
Sergunb | 0:8918a71cdbe9 | 432 | if(key == NULL || ciphertext == NULL) |
Sergunb | 0:8918a71cdbe9 | 433 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 434 | if(message == NULL || messageLength == NULL) |
Sergunb | 0:8918a71cdbe9 | 435 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 436 | |
Sergunb | 0:8918a71cdbe9 | 437 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 438 | TRACE_DEBUG("RSA PKCS #1 v1.5 decryption...\r\n"); |
Sergunb | 0:8918a71cdbe9 | 439 | TRACE_DEBUG(" Modulus:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 440 | TRACE_DEBUG_MPI(" ", &key->n); |
Sergunb | 0:8918a71cdbe9 | 441 | TRACE_DEBUG(" Public exponent:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 442 | TRACE_DEBUG_MPI(" ", &key->e); |
Sergunb | 0:8918a71cdbe9 | 443 | TRACE_DEBUG(" Private exponent:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 444 | TRACE_DEBUG_MPI(" ", &key->d); |
Sergunb | 0:8918a71cdbe9 | 445 | TRACE_DEBUG(" Prime 1:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 446 | TRACE_DEBUG_MPI(" ", &key->p); |
Sergunb | 0:8918a71cdbe9 | 447 | TRACE_DEBUG(" Prime 2:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 448 | TRACE_DEBUG_MPI(" ", &key->q); |
Sergunb | 0:8918a71cdbe9 | 449 | TRACE_DEBUG(" Prime exponent 1:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 450 | TRACE_DEBUG_MPI(" ", &key->dp); |
Sergunb | 0:8918a71cdbe9 | 451 | TRACE_DEBUG(" Prime exponent 2:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 452 | TRACE_DEBUG_MPI(" ", &key->dq); |
Sergunb | 0:8918a71cdbe9 | 453 | TRACE_DEBUG(" Coefficient:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 454 | TRACE_DEBUG_MPI(" ", &key->qinv); |
Sergunb | 0:8918a71cdbe9 | 455 | TRACE_DEBUG(" Ciphertext:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 456 | TRACE_DEBUG_ARRAY(" ", ciphertext, ciphertextLength); |
Sergunb | 0:8918a71cdbe9 | 457 | |
Sergunb | 0:8918a71cdbe9 | 458 | //Initialize multiple-precision integers |
Sergunb | 0:8918a71cdbe9 | 459 | mpiInit(&c); |
Sergunb | 0:8918a71cdbe9 | 460 | mpiInit(&m); |
Sergunb | 0:8918a71cdbe9 | 461 | |
Sergunb | 0:8918a71cdbe9 | 462 | //Get the length in octets of the modulus n |
Sergunb | 0:8918a71cdbe9 | 463 | k = mpiGetByteLength(&key->n); |
Sergunb | 0:8918a71cdbe9 | 464 | |
Sergunb | 0:8918a71cdbe9 | 465 | //Check the length of the ciphertext |
Sergunb | 0:8918a71cdbe9 | 466 | if(ciphertextLength != k || ciphertextLength < 11) |
Sergunb | 0:8918a71cdbe9 | 467 | return ERROR_INVALID_LENGTH; |
Sergunb | 0:8918a71cdbe9 | 468 | |
Sergunb | 0:8918a71cdbe9 | 469 | //Allocate a buffer to store the encoded message EM |
Sergunb | 0:8918a71cdbe9 | 470 | em = cryptoAllocMem(k); |
Sergunb | 0:8918a71cdbe9 | 471 | //Failed to allocate memory? |
Sergunb | 0:8918a71cdbe9 | 472 | if(em == NULL) |
Sergunb | 0:8918a71cdbe9 | 473 | return ERROR_OUT_OF_MEMORY; |
Sergunb | 0:8918a71cdbe9 | 474 | |
Sergunb | 0:8918a71cdbe9 | 475 | //Start of exception handling block |
Sergunb | 0:8918a71cdbe9 | 476 | do |
Sergunb | 0:8918a71cdbe9 | 477 | { |
Sergunb | 0:8918a71cdbe9 | 478 | //Convert the ciphertext to an integer ciphertext representative c |
Sergunb | 0:8918a71cdbe9 | 479 | error = mpiReadRaw(&c, ciphertext, ciphertextLength); |
Sergunb | 0:8918a71cdbe9 | 480 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 481 | if(error) |
Sergunb | 0:8918a71cdbe9 | 482 | break; |
Sergunb | 0:8918a71cdbe9 | 483 | |
Sergunb | 0:8918a71cdbe9 | 484 | //Apply the RSADP decryption primitive |
Sergunb | 0:8918a71cdbe9 | 485 | error = rsadp(key, &c, &m); |
Sergunb | 0:8918a71cdbe9 | 486 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 487 | if(error) |
Sergunb | 0:8918a71cdbe9 | 488 | break; |
Sergunb | 0:8918a71cdbe9 | 489 | |
Sergunb | 0:8918a71cdbe9 | 490 | //Convert the message representative m to an encoded message EM of length k octets |
Sergunb | 0:8918a71cdbe9 | 491 | error = mpiWriteRaw(&m, em, k); |
Sergunb | 0:8918a71cdbe9 | 492 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 493 | if(error) |
Sergunb | 0:8918a71cdbe9 | 494 | break; |
Sergunb | 0:8918a71cdbe9 | 495 | |
Sergunb | 0:8918a71cdbe9 | 496 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 497 | TRACE_DEBUG(" Encoded message\r\n"); |
Sergunb | 0:8918a71cdbe9 | 498 | TRACE_DEBUG_ARRAY(" ", em, k); |
Sergunb | 0:8918a71cdbe9 | 499 | |
Sergunb | 0:8918a71cdbe9 | 500 | //The first octet of EM must have a value of 0x00 |
Sergunb | 0:8918a71cdbe9 | 501 | //and the block type BT shall be 0x02 |
Sergunb | 0:8918a71cdbe9 | 502 | if(em[0] != 0x00 || em[1] != 0x02) |
Sergunb | 0:8918a71cdbe9 | 503 | { |
Sergunb | 0:8918a71cdbe9 | 504 | //Report an error |
Sergunb | 0:8918a71cdbe9 | 505 | error = ERROR_UNEXPECTED_VALUE; |
Sergunb | 0:8918a71cdbe9 | 506 | break; |
Sergunb | 0:8918a71cdbe9 | 507 | } |
Sergunb | 0:8918a71cdbe9 | 508 | |
Sergunb | 0:8918a71cdbe9 | 509 | //An octet with hexadecimal value 0x00 is used to separate PS from M |
Sergunb | 0:8918a71cdbe9 | 510 | for(i = 2; i < k && em[i] != 0x00; i++); |
Sergunb | 0:8918a71cdbe9 | 511 | |
Sergunb | 0:8918a71cdbe9 | 512 | //Check whether the padding string is valid |
Sergunb | 0:8918a71cdbe9 | 513 | if(i < 10 || i >= k) |
Sergunb | 0:8918a71cdbe9 | 514 | { |
Sergunb | 0:8918a71cdbe9 | 515 | //Report an error |
Sergunb | 0:8918a71cdbe9 | 516 | error = ERROR_INVALID_PADDING; |
Sergunb | 0:8918a71cdbe9 | 517 | break; |
Sergunb | 0:8918a71cdbe9 | 518 | } |
Sergunb | 0:8918a71cdbe9 | 519 | |
Sergunb | 0:8918a71cdbe9 | 520 | //Ensure that the output buffer is large enough |
Sergunb | 0:8918a71cdbe9 | 521 | if(messageSize < (k - i - 1)) |
Sergunb | 0:8918a71cdbe9 | 522 | { |
Sergunb | 0:8918a71cdbe9 | 523 | //Report an error |
Sergunb | 0:8918a71cdbe9 | 524 | error = ERROR_INVALID_LENGTH; |
Sergunb | 0:8918a71cdbe9 | 525 | break; |
Sergunb | 0:8918a71cdbe9 | 526 | } |
Sergunb | 0:8918a71cdbe9 | 527 | |
Sergunb | 0:8918a71cdbe9 | 528 | //Recover the length of the message |
Sergunb | 0:8918a71cdbe9 | 529 | *messageLength = k - i - 1; |
Sergunb | 0:8918a71cdbe9 | 530 | //Copy the message contents |
Sergunb | 0:8918a71cdbe9 | 531 | memcpy(message, em + i + 1, *messageLength); |
Sergunb | 0:8918a71cdbe9 | 532 | |
Sergunb | 0:8918a71cdbe9 | 533 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 534 | TRACE_DEBUG(" Message:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 535 | TRACE_DEBUG_ARRAY(" ", message, *messageLength); |
Sergunb | 0:8918a71cdbe9 | 536 | |
Sergunb | 0:8918a71cdbe9 | 537 | //End of exception handling block |
Sergunb | 0:8918a71cdbe9 | 538 | } while(0); |
Sergunb | 0:8918a71cdbe9 | 539 | |
Sergunb | 0:8918a71cdbe9 | 540 | //Release multiple precision integers |
Sergunb | 0:8918a71cdbe9 | 541 | mpiFree(&c); |
Sergunb | 0:8918a71cdbe9 | 542 | mpiFree(&m); |
Sergunb | 0:8918a71cdbe9 | 543 | //Free previously allocated memory |
Sergunb | 0:8918a71cdbe9 | 544 | cryptoFreeMem(em); |
Sergunb | 0:8918a71cdbe9 | 545 | |
Sergunb | 0:8918a71cdbe9 | 546 | //Return status code |
Sergunb | 0:8918a71cdbe9 | 547 | return error; |
Sergunb | 0:8918a71cdbe9 | 548 | } |
Sergunb | 0:8918a71cdbe9 | 549 | |
Sergunb | 0:8918a71cdbe9 | 550 | |
Sergunb | 0:8918a71cdbe9 | 551 | /** |
Sergunb | 0:8918a71cdbe9 | 552 | * @brief PKCS #1 v1.5 signature generation operation |
Sergunb | 0:8918a71cdbe9 | 553 | * @param[in] key Signer's RSA private key |
Sergunb | 0:8918a71cdbe9 | 554 | * @param[in] hash Hash function used to digest the message |
Sergunb | 0:8918a71cdbe9 | 555 | * @param[in] digest Digest of the message to be signed |
Sergunb | 0:8918a71cdbe9 | 556 | * @param[out] signature Resulting signature |
Sergunb | 0:8918a71cdbe9 | 557 | * @param[out] signatureLength Length of the resulting signature |
Sergunb | 0:8918a71cdbe9 | 558 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 559 | **/ |
Sergunb | 0:8918a71cdbe9 | 560 | |
Sergunb | 0:8918a71cdbe9 | 561 | error_t rsassaPkcs1v15Sign(const RsaPrivateKey *key, const HashAlgo *hash, |
Sergunb | 0:8918a71cdbe9 | 562 | const uint8_t *digest, uint8_t *signature, size_t *signatureLength) |
Sergunb | 0:8918a71cdbe9 | 563 | { |
Sergunb | 0:8918a71cdbe9 | 564 | error_t error; |
Sergunb | 0:8918a71cdbe9 | 565 | uint_t k; |
Sergunb | 0:8918a71cdbe9 | 566 | uint8_t *em; |
Sergunb | 0:8918a71cdbe9 | 567 | Mpi m; |
Sergunb | 0:8918a71cdbe9 | 568 | Mpi s; |
Sergunb | 0:8918a71cdbe9 | 569 | |
Sergunb | 0:8918a71cdbe9 | 570 | //Check parameters |
Sergunb | 0:8918a71cdbe9 | 571 | if(key == NULL || hash == NULL || digest == NULL) |
Sergunb | 0:8918a71cdbe9 | 572 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 573 | if(signature == NULL || signatureLength == NULL) |
Sergunb | 0:8918a71cdbe9 | 574 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 575 | |
Sergunb | 0:8918a71cdbe9 | 576 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 577 | TRACE_DEBUG("RSA PKCS #1 v1.5 signature generation...\r\n"); |
Sergunb | 0:8918a71cdbe9 | 578 | TRACE_DEBUG(" Modulus:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 579 | TRACE_DEBUG_MPI(" ", &key->n); |
Sergunb | 0:8918a71cdbe9 | 580 | TRACE_DEBUG(" Public exponent:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 581 | TRACE_DEBUG_MPI(" ", &key->e); |
Sergunb | 0:8918a71cdbe9 | 582 | TRACE_DEBUG(" Private exponent:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 583 | TRACE_DEBUG_MPI(" ", &key->d); |
Sergunb | 0:8918a71cdbe9 | 584 | TRACE_DEBUG(" Prime 1:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 585 | TRACE_DEBUG_MPI(" ", &key->p); |
Sergunb | 0:8918a71cdbe9 | 586 | TRACE_DEBUG(" Prime 2:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 587 | TRACE_DEBUG_MPI(" ", &key->q); |
Sergunb | 0:8918a71cdbe9 | 588 | TRACE_DEBUG(" Prime exponent 1:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 589 | TRACE_DEBUG_MPI(" ", &key->dp); |
Sergunb | 0:8918a71cdbe9 | 590 | TRACE_DEBUG(" Prime exponent 2:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 591 | TRACE_DEBUG_MPI(" ", &key->dq); |
Sergunb | 0:8918a71cdbe9 | 592 | TRACE_DEBUG(" Coefficient:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 593 | TRACE_DEBUG_MPI(" ", &key->qinv); |
Sergunb | 0:8918a71cdbe9 | 594 | TRACE_DEBUG(" Message digest:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 595 | TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize); |
Sergunb | 0:8918a71cdbe9 | 596 | |
Sergunb | 0:8918a71cdbe9 | 597 | //Initialize multiple-precision integers |
Sergunb | 0:8918a71cdbe9 | 598 | mpiInit(&m); |
Sergunb | 0:8918a71cdbe9 | 599 | mpiInit(&s); |
Sergunb | 0:8918a71cdbe9 | 600 | |
Sergunb | 0:8918a71cdbe9 | 601 | //Get the length in octets of the modulus n |
Sergunb | 0:8918a71cdbe9 | 602 | k = mpiGetByteLength(&key->n); |
Sergunb | 0:8918a71cdbe9 | 603 | //Point to the buffer where the encoded message EM will be generated |
Sergunb | 0:8918a71cdbe9 | 604 | em = signature; |
Sergunb | 0:8918a71cdbe9 | 605 | |
Sergunb | 0:8918a71cdbe9 | 606 | //Apply the EMSA-PKCS1-v1.5 encoding operation |
Sergunb | 0:8918a71cdbe9 | 607 | error = emsaPkcs1v15Encode(hash, digest, em, k); |
Sergunb | 0:8918a71cdbe9 | 608 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 609 | if(error) |
Sergunb | 0:8918a71cdbe9 | 610 | return error; |
Sergunb | 0:8918a71cdbe9 | 611 | |
Sergunb | 0:8918a71cdbe9 | 612 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 613 | TRACE_DEBUG(" Encoded message\r\n"); |
Sergunb | 0:8918a71cdbe9 | 614 | TRACE_DEBUG_ARRAY(" ", em, k); |
Sergunb | 0:8918a71cdbe9 | 615 | |
Sergunb | 0:8918a71cdbe9 | 616 | //Start of exception handling block |
Sergunb | 0:8918a71cdbe9 | 617 | do |
Sergunb | 0:8918a71cdbe9 | 618 | { |
Sergunb | 0:8918a71cdbe9 | 619 | //Convert the encoded message EM to an integer message representative m |
Sergunb | 0:8918a71cdbe9 | 620 | error = mpiReadRaw(&m, em, k); |
Sergunb | 0:8918a71cdbe9 | 621 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 622 | if(error) |
Sergunb | 0:8918a71cdbe9 | 623 | break; |
Sergunb | 0:8918a71cdbe9 | 624 | |
Sergunb | 0:8918a71cdbe9 | 625 | //Apply the RSASP1 signature primitive |
Sergunb | 0:8918a71cdbe9 | 626 | error = rsasp1(key, &m, &s); |
Sergunb | 0:8918a71cdbe9 | 627 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 628 | if(error) |
Sergunb | 0:8918a71cdbe9 | 629 | break; |
Sergunb | 0:8918a71cdbe9 | 630 | |
Sergunb | 0:8918a71cdbe9 | 631 | //Convert the signature representative s to a signature of length k octets |
Sergunb | 0:8918a71cdbe9 | 632 | error = mpiWriteRaw(&s, signature, k); |
Sergunb | 0:8918a71cdbe9 | 633 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 634 | if(error) |
Sergunb | 0:8918a71cdbe9 | 635 | break; |
Sergunb | 0:8918a71cdbe9 | 636 | |
Sergunb | 0:8918a71cdbe9 | 637 | //Length of the resulting signature |
Sergunb | 0:8918a71cdbe9 | 638 | *signatureLength = k; |
Sergunb | 0:8918a71cdbe9 | 639 | |
Sergunb | 0:8918a71cdbe9 | 640 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 641 | TRACE_DEBUG(" Signature:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 642 | TRACE_DEBUG_ARRAY(" ", signature, *signatureLength); |
Sergunb | 0:8918a71cdbe9 | 643 | |
Sergunb | 0:8918a71cdbe9 | 644 | //End of exception handling block |
Sergunb | 0:8918a71cdbe9 | 645 | } while(0); |
Sergunb | 0:8918a71cdbe9 | 646 | |
Sergunb | 0:8918a71cdbe9 | 647 | //Free previously allocated memory |
Sergunb | 0:8918a71cdbe9 | 648 | mpiFree(&m); |
Sergunb | 0:8918a71cdbe9 | 649 | mpiFree(&s); |
Sergunb | 0:8918a71cdbe9 | 650 | |
Sergunb | 0:8918a71cdbe9 | 651 | //Return status code |
Sergunb | 0:8918a71cdbe9 | 652 | return error; |
Sergunb | 0:8918a71cdbe9 | 653 | } |
Sergunb | 0:8918a71cdbe9 | 654 | |
Sergunb | 0:8918a71cdbe9 | 655 | |
Sergunb | 0:8918a71cdbe9 | 656 | /** |
Sergunb | 0:8918a71cdbe9 | 657 | * @brief PKCS #1 v1.5 signature verification operation |
Sergunb | 0:8918a71cdbe9 | 658 | * @param[in] key Signer's RSA public key |
Sergunb | 0:8918a71cdbe9 | 659 | * @param[in] hash Hash function used to digest the message |
Sergunb | 0:8918a71cdbe9 | 660 | * @param[in] digest Digest of the message whose signature is to be verified |
Sergunb | 0:8918a71cdbe9 | 661 | * @param[in] signature Signature to be verified |
Sergunb | 0:8918a71cdbe9 | 662 | * @param[in] signatureLength Length of the signature to be verified |
Sergunb | 0:8918a71cdbe9 | 663 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 664 | **/ |
Sergunb | 0:8918a71cdbe9 | 665 | |
Sergunb | 0:8918a71cdbe9 | 666 | error_t rsassaPkcs1v15Verify(const RsaPublicKey *key, const HashAlgo *hash, |
Sergunb | 0:8918a71cdbe9 | 667 | const uint8_t *digest, const uint8_t *signature, size_t signatureLength) |
Sergunb | 0:8918a71cdbe9 | 668 | { |
Sergunb | 0:8918a71cdbe9 | 669 | error_t error; |
Sergunb | 0:8918a71cdbe9 | 670 | uint_t k; |
Sergunb | 0:8918a71cdbe9 | 671 | uint8_t *em; |
Sergunb | 0:8918a71cdbe9 | 672 | const uint8_t *oid; |
Sergunb | 0:8918a71cdbe9 | 673 | size_t oidLength; |
Sergunb | 0:8918a71cdbe9 | 674 | const uint8_t *d; |
Sergunb | 0:8918a71cdbe9 | 675 | size_t dLength; |
Sergunb | 0:8918a71cdbe9 | 676 | Mpi s; |
Sergunb | 0:8918a71cdbe9 | 677 | Mpi m; |
Sergunb | 0:8918a71cdbe9 | 678 | |
Sergunb | 0:8918a71cdbe9 | 679 | //Check parameters |
Sergunb | 0:8918a71cdbe9 | 680 | if(key == NULL || hash == NULL || digest == NULL || signature == NULL) |
Sergunb | 0:8918a71cdbe9 | 681 | return ERROR_INVALID_PARAMETER; |
Sergunb | 0:8918a71cdbe9 | 682 | |
Sergunb | 0:8918a71cdbe9 | 683 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 684 | TRACE_DEBUG("RSA PKCS #1 v1.5 signature verification...\r\n"); |
Sergunb | 0:8918a71cdbe9 | 685 | TRACE_DEBUG(" Modulus:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 686 | TRACE_DEBUG_MPI(" ", &key->n); |
Sergunb | 0:8918a71cdbe9 | 687 | TRACE_DEBUG(" Public exponent:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 688 | TRACE_DEBUG_MPI(" ", &key->e); |
Sergunb | 0:8918a71cdbe9 | 689 | TRACE_DEBUG(" Message digest:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 690 | TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize); |
Sergunb | 0:8918a71cdbe9 | 691 | TRACE_DEBUG(" Signature:\r\n"); |
Sergunb | 0:8918a71cdbe9 | 692 | TRACE_DEBUG_ARRAY(" ", signature, signatureLength); |
Sergunb | 0:8918a71cdbe9 | 693 | |
Sergunb | 0:8918a71cdbe9 | 694 | //Initialize multiple-precision integers |
Sergunb | 0:8918a71cdbe9 | 695 | mpiInit(&s); |
Sergunb | 0:8918a71cdbe9 | 696 | mpiInit(&m); |
Sergunb | 0:8918a71cdbe9 | 697 | |
Sergunb | 0:8918a71cdbe9 | 698 | //Get the length in octets of the modulus n |
Sergunb | 0:8918a71cdbe9 | 699 | k = mpiGetByteLength(&key->n); |
Sergunb | 0:8918a71cdbe9 | 700 | |
Sergunb | 0:8918a71cdbe9 | 701 | //Check the length of the signature |
Sergunb | 0:8918a71cdbe9 | 702 | if(signatureLength != k) |
Sergunb | 0:8918a71cdbe9 | 703 | return ERROR_INVALID_LENGTH; |
Sergunb | 0:8918a71cdbe9 | 704 | |
Sergunb | 0:8918a71cdbe9 | 705 | //Allocate a memory buffer to hold the encoded message |
Sergunb | 0:8918a71cdbe9 | 706 | em = cryptoAllocMem(k); |
Sergunb | 0:8918a71cdbe9 | 707 | //Failed to allocate memory? |
Sergunb | 0:8918a71cdbe9 | 708 | if(em == NULL) |
Sergunb | 0:8918a71cdbe9 | 709 | return ERROR_OUT_OF_MEMORY; |
Sergunb | 0:8918a71cdbe9 | 710 | |
Sergunb | 0:8918a71cdbe9 | 711 | //Start of exception handling block |
Sergunb | 0:8918a71cdbe9 | 712 | do |
Sergunb | 0:8918a71cdbe9 | 713 | { |
Sergunb | 0:8918a71cdbe9 | 714 | //Convert the signature to an integer signature representative s |
Sergunb | 0:8918a71cdbe9 | 715 | error = mpiReadRaw(&s, signature, signatureLength); |
Sergunb | 0:8918a71cdbe9 | 716 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 717 | if(error) |
Sergunb | 0:8918a71cdbe9 | 718 | break; |
Sergunb | 0:8918a71cdbe9 | 719 | |
Sergunb | 0:8918a71cdbe9 | 720 | //Apply the RSAVP1 verification primitive |
Sergunb | 0:8918a71cdbe9 | 721 | error = rsavp1(key, &s, &m); |
Sergunb | 0:8918a71cdbe9 | 722 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 723 | if(error) |
Sergunb | 0:8918a71cdbe9 | 724 | break; |
Sergunb | 0:8918a71cdbe9 | 725 | |
Sergunb | 0:8918a71cdbe9 | 726 | //Convert the message representative m to an encoded message EM of length k octets |
Sergunb | 0:8918a71cdbe9 | 727 | error = mpiWriteRaw(&m, em, k); |
Sergunb | 0:8918a71cdbe9 | 728 | //Conversion failed? |
Sergunb | 0:8918a71cdbe9 | 729 | if(error) |
Sergunb | 0:8918a71cdbe9 | 730 | break; |
Sergunb | 0:8918a71cdbe9 | 731 | |
Sergunb | 0:8918a71cdbe9 | 732 | //Debug message |
Sergunb | 0:8918a71cdbe9 | 733 | TRACE_DEBUG(" Encoded message\r\n"); |
Sergunb | 0:8918a71cdbe9 | 734 | TRACE_DEBUG_ARRAY(" ", em, k); |
Sergunb | 0:8918a71cdbe9 | 735 | |
Sergunb | 0:8918a71cdbe9 | 736 | //Parse the encoded message EM |
Sergunb | 0:8918a71cdbe9 | 737 | error = emsaPkcs1v15Decode(em, k, &oid, &oidLength, &d, &dLength); |
Sergunb | 0:8918a71cdbe9 | 738 | //Any error to report? |
Sergunb | 0:8918a71cdbe9 | 739 | if(error) |
Sergunb | 0:8918a71cdbe9 | 740 | break; |
Sergunb | 0:8918a71cdbe9 | 741 | |
Sergunb | 0:8918a71cdbe9 | 742 | //Assume an error... |
Sergunb | 0:8918a71cdbe9 | 743 | error = ERROR_INVALID_SIGNATURE_ALGO; |
Sergunb | 0:8918a71cdbe9 | 744 | //Ensure the hash algorithm identifier matches the OID |
Sergunb | 0:8918a71cdbe9 | 745 | if(oidComp(oid, oidLength, hash->oid, hash->oidSize)) |
Sergunb | 0:8918a71cdbe9 | 746 | break; |
Sergunb | 0:8918a71cdbe9 | 747 | //Check the length of the digest |
Sergunb | 0:8918a71cdbe9 | 748 | if(dLength != hash->digestSize) |
Sergunb | 0:8918a71cdbe9 | 749 | break; |
Sergunb | 0:8918a71cdbe9 | 750 | |
Sergunb | 0:8918a71cdbe9 | 751 | //Compare the message digest |
Sergunb | 0:8918a71cdbe9 | 752 | error = memcmp(digest, d, dLength) ? ERROR_INVALID_SIGNATURE : NO_ERROR; |
Sergunb | 0:8918a71cdbe9 | 753 | |
Sergunb | 0:8918a71cdbe9 | 754 | //End of exception handling block |
Sergunb | 0:8918a71cdbe9 | 755 | } while(0); |
Sergunb | 0:8918a71cdbe9 | 756 | |
Sergunb | 0:8918a71cdbe9 | 757 | //Release multiple precision integers |
Sergunb | 0:8918a71cdbe9 | 758 | mpiFree(&s); |
Sergunb | 0:8918a71cdbe9 | 759 | mpiFree(&m); |
Sergunb | 0:8918a71cdbe9 | 760 | //Free previously allocated memory |
Sergunb | 0:8918a71cdbe9 | 761 | cryptoFreeMem(em); |
Sergunb | 0:8918a71cdbe9 | 762 | |
Sergunb | 0:8918a71cdbe9 | 763 | //Return status code |
Sergunb | 0:8918a71cdbe9 | 764 | return error; |
Sergunb | 0:8918a71cdbe9 | 765 | } |
Sergunb | 0:8918a71cdbe9 | 766 | |
Sergunb | 0:8918a71cdbe9 | 767 | |
Sergunb | 0:8918a71cdbe9 | 768 | /** |
Sergunb | 0:8918a71cdbe9 | 769 | * @brief PKCS #1 v1.5 encoding method |
Sergunb | 0:8918a71cdbe9 | 770 | * @param[in] hash Hash function used to digest the message |
Sergunb | 0:8918a71cdbe9 | 771 | * @param[in] digest Digest of the message to be signed |
Sergunb | 0:8918a71cdbe9 | 772 | * @param[out] em Encoded message |
Sergunb | 0:8918a71cdbe9 | 773 | * @param[in] emLength Intended length of the encoded message |
Sergunb | 0:8918a71cdbe9 | 774 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 775 | **/ |
Sergunb | 0:8918a71cdbe9 | 776 | |
Sergunb | 0:8918a71cdbe9 | 777 | error_t emsaPkcs1v15Encode(const HashAlgo *hash, |
Sergunb | 0:8918a71cdbe9 | 778 | const uint8_t *digest, uint8_t *em, size_t emLength) |
Sergunb | 0:8918a71cdbe9 | 779 | { |
Sergunb | 0:8918a71cdbe9 | 780 | uint_t i; |
Sergunb | 0:8918a71cdbe9 | 781 | size_t paddingLength; |
Sergunb | 0:8918a71cdbe9 | 782 | |
Sergunb | 0:8918a71cdbe9 | 783 | //Ensure the length of the digest is valid |
Sergunb | 0:8918a71cdbe9 | 784 | if((hash->oidSize + hash->digestSize + 21) > emLength) |
Sergunb | 0:8918a71cdbe9 | 785 | return ERROR_INVALID_LENGTH; |
Sergunb | 0:8918a71cdbe9 | 786 | |
Sergunb | 0:8918a71cdbe9 | 787 | //The leading 0x00 octet ensures that the encoded message, |
Sergunb | 0:8918a71cdbe9 | 788 | //converted to an integer, is less than the modulus |
Sergunb | 0:8918a71cdbe9 | 789 | em[0] = 0x00; |
Sergunb | 0:8918a71cdbe9 | 790 | //Block type 0x01 is used for private-key operations |
Sergunb | 0:8918a71cdbe9 | 791 | em[1] = 0x01; |
Sergunb | 0:8918a71cdbe9 | 792 | |
Sergunb | 0:8918a71cdbe9 | 793 | //Compute the length of the padding string PS |
Sergunb | 0:8918a71cdbe9 | 794 | paddingLength = emLength - hash->oidSize - hash->digestSize - 13; |
Sergunb | 0:8918a71cdbe9 | 795 | //Fill the padding string with 0xFF |
Sergunb | 0:8918a71cdbe9 | 796 | memset(em + 2, 0xFF, paddingLength); |
Sergunb | 0:8918a71cdbe9 | 797 | |
Sergunb | 0:8918a71cdbe9 | 798 | //Point to the byte that follows PS |
Sergunb | 0:8918a71cdbe9 | 799 | i = paddingLength + 2; |
Sergunb | 0:8918a71cdbe9 | 800 | //Append a 0x00 octet to PS |
Sergunb | 0:8918a71cdbe9 | 801 | em[i++] = 0x00; |
Sergunb | 0:8918a71cdbe9 | 802 | |
Sergunb | 0:8918a71cdbe9 | 803 | //Encode the DigestInfo using ASN.1 |
Sergunb | 0:8918a71cdbe9 | 804 | em[i++] = ASN1_ENCODING_CONSTRUCTED | ASN1_TYPE_SEQUENCE; |
Sergunb | 0:8918a71cdbe9 | 805 | em[i++] = (uint8_t) (hash->oidSize + hash->digestSize + 8); |
Sergunb | 0:8918a71cdbe9 | 806 | em[i++] = ASN1_ENCODING_CONSTRUCTED | ASN1_TYPE_SEQUENCE; |
Sergunb | 0:8918a71cdbe9 | 807 | em[i++] = (uint8_t) (hash->oidSize + 4); |
Sergunb | 0:8918a71cdbe9 | 808 | em[i++] = ASN1_TYPE_OBJECT_IDENTIFIER; |
Sergunb | 0:8918a71cdbe9 | 809 | em[i++] = (uint8_t) hash->oidSize; |
Sergunb | 0:8918a71cdbe9 | 810 | |
Sergunb | 0:8918a71cdbe9 | 811 | //Copy the hash algorithm OID |
Sergunb | 0:8918a71cdbe9 | 812 | memcpy(em + i, hash->oid, hash->oidSize); |
Sergunb | 0:8918a71cdbe9 | 813 | i += hash->oidSize; |
Sergunb | 0:8918a71cdbe9 | 814 | |
Sergunb | 0:8918a71cdbe9 | 815 | //Encode the rest of the ASN.1 structure |
Sergunb | 0:8918a71cdbe9 | 816 | em[i++] = ASN1_TYPE_NULL; |
Sergunb | 0:8918a71cdbe9 | 817 | em[i++] = 0; |
Sergunb | 0:8918a71cdbe9 | 818 | em[i++] = ASN1_TYPE_OCTET_STRING; |
Sergunb | 0:8918a71cdbe9 | 819 | em[i++] = (uint8_t) hash->digestSize; |
Sergunb | 0:8918a71cdbe9 | 820 | |
Sergunb | 0:8918a71cdbe9 | 821 | //Append the hash value |
Sergunb | 0:8918a71cdbe9 | 822 | memcpy(em + i, digest, hash->digestSize); |
Sergunb | 0:8918a71cdbe9 | 823 | |
Sergunb | 0:8918a71cdbe9 | 824 | //Successful processing |
Sergunb | 0:8918a71cdbe9 | 825 | return NO_ERROR; |
Sergunb | 0:8918a71cdbe9 | 826 | } |
Sergunb | 0:8918a71cdbe9 | 827 | |
Sergunb | 0:8918a71cdbe9 | 828 | |
Sergunb | 0:8918a71cdbe9 | 829 | /** |
Sergunb | 0:8918a71cdbe9 | 830 | * @brief PKCS #1 v1.5 decoding method |
Sergunb | 0:8918a71cdbe9 | 831 | * @param[in] em Encoded message |
Sergunb | 0:8918a71cdbe9 | 832 | * @param[in] emLength Length of the encoded message |
Sergunb | 0:8918a71cdbe9 | 833 | * @param[out] oid Hash algorithm OID |
Sergunb | 0:8918a71cdbe9 | 834 | * @param[out] oidLength Length of the hash algorithm OID |
Sergunb | 0:8918a71cdbe9 | 835 | * @param[out] digest Digest value |
Sergunb | 0:8918a71cdbe9 | 836 | * @param[out] digestLength Length of the digest value |
Sergunb | 0:8918a71cdbe9 | 837 | |
Sergunb | 0:8918a71cdbe9 | 838 | * @return Error code |
Sergunb | 0:8918a71cdbe9 | 839 | **/ |
Sergunb | 0:8918a71cdbe9 | 840 | |
Sergunb | 0:8918a71cdbe9 | 841 | error_t emsaPkcs1v15Decode(const uint8_t *em, size_t emLength, const uint8_t **oid, |
Sergunb | 0:8918a71cdbe9 | 842 | size_t *oidLength, const uint8_t **digest, size_t *digestLength) |
Sergunb | 0:8918a71cdbe9 | 843 | { |
Sergunb | 0:8918a71cdbe9 | 844 | error_t error; |
Sergunb | 0:8918a71cdbe9 | 845 | uint_t i; |
Sergunb | 0:8918a71cdbe9 | 846 | size_t length; |
Sergunb | 0:8918a71cdbe9 | 847 | const uint8_t *data; |
Sergunb | 0:8918a71cdbe9 | 848 | Asn1Tag tag; |
Sergunb | 0:8918a71cdbe9 | 849 | |
Sergunb | 0:8918a71cdbe9 | 850 | //Check the length of the encoded message EM |
Sergunb | 0:8918a71cdbe9 | 851 | if(emLength < 11) |
Sergunb | 0:8918a71cdbe9 | 852 | return ERROR_INVALID_LENGTH; |
Sergunb | 0:8918a71cdbe9 | 853 | |
Sergunb | 0:8918a71cdbe9 | 854 | //The first octet of EM must have a value of 0x00 |
Sergunb | 0:8918a71cdbe9 | 855 | if(em[0] != 0x00) |
Sergunb | 0:8918a71cdbe9 | 856 | return ERROR_UNEXPECTED_VALUE; |
Sergunb | 0:8918a71cdbe9 | 857 | //The block type BT shall be 0x01 |
Sergunb | 0:8918a71cdbe9 | 858 | if(em[1] != 0x01) |
Sergunb | 0:8918a71cdbe9 | 859 | return ERROR_UNEXPECTED_VALUE; |
Sergunb | 0:8918a71cdbe9 | 860 | |
Sergunb | 0:8918a71cdbe9 | 861 | //Check the padding string PS |
Sergunb | 0:8918a71cdbe9 | 862 | for(i = 2; i < emLength; i++) |
Sergunb | 0:8918a71cdbe9 | 863 | { |
Sergunb | 0:8918a71cdbe9 | 864 | //A 0x00 octet indicates the end of the padding string |
Sergunb | 0:8918a71cdbe9 | 865 | if(em[i] == 0x00) |
Sergunb | 0:8918a71cdbe9 | 866 | break; |
Sergunb | 0:8918a71cdbe9 | 867 | //Each byte of PS must be set to 0xFF when the block type is 0x01 |
Sergunb | 0:8918a71cdbe9 | 868 | if(em[i] != 0xFF) |
Sergunb | 0:8918a71cdbe9 | 869 | return ERROR_INVALID_PADDING; |
Sergunb | 0:8918a71cdbe9 | 870 | } |
Sergunb | 0:8918a71cdbe9 | 871 | |
Sergunb | 0:8918a71cdbe9 | 872 | //Check whether the padding string is properly terminated |
Sergunb | 0:8918a71cdbe9 | 873 | if(i >= emLength) |
Sergunb | 0:8918a71cdbe9 | 874 | return ERROR_INVALID_PADDING; |
Sergunb | 0:8918a71cdbe9 | 875 | //The length of PS cannot be less than 8 octets |
Sergunb | 0:8918a71cdbe9 | 876 | if(i < 10) |
Sergunb | 0:8918a71cdbe9 | 877 | return ERROR_INVALID_PADDING; |
Sergunb | 0:8918a71cdbe9 | 878 | |
Sergunb | 0:8918a71cdbe9 | 879 | //Point to the DigestInfo structure |
Sergunb | 0:8918a71cdbe9 | 880 | data = em + i + 1; |
Sergunb | 0:8918a71cdbe9 | 881 | length = emLength - i - 1; |
Sergunb | 0:8918a71cdbe9 | 882 | |
Sergunb | 0:8918a71cdbe9 | 883 | //Read the contents of the DigestInfo structure |
Sergunb | 0:8918a71cdbe9 | 884 | error = asn1ReadTag(data, length, &tag); |
Sergunb | 0:8918a71cdbe9 | 885 | //Failed to decode the ASN.1 tag? |
Sergunb | 0:8918a71cdbe9 | 886 | if(error) |
Sergunb | 0:8918a71cdbe9 | 887 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 888 | |
Sergunb | 0:8918a71cdbe9 | 889 | //Enforce encoding, class and type |
Sergunb | 0:8918a71cdbe9 | 890 | if(!tag.constructed || tag.objType != ASN1_TYPE_SEQUENCE) |
Sergunb | 0:8918a71cdbe9 | 891 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 892 | |
Sergunb | 0:8918a71cdbe9 | 893 | //Point to the DigestAlgorithm structure |
Sergunb | 0:8918a71cdbe9 | 894 | data = tag.value; |
Sergunb | 0:8918a71cdbe9 | 895 | length = tag.length; |
Sergunb | 0:8918a71cdbe9 | 896 | |
Sergunb | 0:8918a71cdbe9 | 897 | //Decode the DigestAlgorithm tag |
Sergunb | 0:8918a71cdbe9 | 898 | error = asn1ReadTag(data, length, &tag); |
Sergunb | 0:8918a71cdbe9 | 899 | //Failed to decode the ASN.1 tag? |
Sergunb | 0:8918a71cdbe9 | 900 | if(error) |
Sergunb | 0:8918a71cdbe9 | 901 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 902 | |
Sergunb | 0:8918a71cdbe9 | 903 | //Enforce encoding, class and type |
Sergunb | 0:8918a71cdbe9 | 904 | if(!tag.constructed || tag.objType != ASN1_TYPE_SEQUENCE) |
Sergunb | 0:8918a71cdbe9 | 905 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 906 | |
Sergunb | 0:8918a71cdbe9 | 907 | //Save the location of the next tag |
Sergunb | 0:8918a71cdbe9 | 908 | data += tag.totalLength; |
Sergunb | 0:8918a71cdbe9 | 909 | length -= tag.totalLength; |
Sergunb | 0:8918a71cdbe9 | 910 | |
Sergunb | 0:8918a71cdbe9 | 911 | //Decode the AlgorithmIdentifier tag |
Sergunb | 0:8918a71cdbe9 | 912 | error = asn1ReadTag(tag.value, tag.length, &tag); |
Sergunb | 0:8918a71cdbe9 | 913 | //Failed to decode the ASN.1 tag? |
Sergunb | 0:8918a71cdbe9 | 914 | if(error) |
Sergunb | 0:8918a71cdbe9 | 915 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 916 | |
Sergunb | 0:8918a71cdbe9 | 917 | //Enforce encoding, class and type |
Sergunb | 0:8918a71cdbe9 | 918 | if(tag.constructed || tag.objType != ASN1_TYPE_OBJECT_IDENTIFIER) |
Sergunb | 0:8918a71cdbe9 | 919 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 920 | |
Sergunb | 0:8918a71cdbe9 | 921 | //Save the hash algorithm OID |
Sergunb | 0:8918a71cdbe9 | 922 | *oid = tag.value; |
Sergunb | 0:8918a71cdbe9 | 923 | *oidLength = tag.length; |
Sergunb | 0:8918a71cdbe9 | 924 | |
Sergunb | 0:8918a71cdbe9 | 925 | //Decode the DigestValue tag |
Sergunb | 0:8918a71cdbe9 | 926 | error = asn1ReadTag(data, length, &tag); |
Sergunb | 0:8918a71cdbe9 | 927 | //Failed to decode the ASN.1 tag? |
Sergunb | 0:8918a71cdbe9 | 928 | if(error) |
Sergunb | 0:8918a71cdbe9 | 929 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 930 | |
Sergunb | 0:8918a71cdbe9 | 931 | //Enforce encoding, class and type |
Sergunb | 0:8918a71cdbe9 | 932 | if(tag.constructed || tag.objType != ASN1_TYPE_OCTET_STRING) |
Sergunb | 0:8918a71cdbe9 | 933 | return ERROR_INVALID_TAG; |
Sergunb | 0:8918a71cdbe9 | 934 | |
Sergunb | 0:8918a71cdbe9 | 935 | //Save the hash value |
Sergunb | 0:8918a71cdbe9 | 936 | *digest = tag.value; |
Sergunb | 0:8918a71cdbe9 | 937 | *digestLength = tag.length; |
Sergunb | 0:8918a71cdbe9 | 938 | |
Sergunb | 0:8918a71cdbe9 | 939 | //EM successfully decoded |
Sergunb | 0:8918a71cdbe9 | 940 | return NO_ERROR; |
Sergunb | 0:8918a71cdbe9 | 941 | } |
Sergunb | 0:8918a71cdbe9 | 942 | |
Sergunb | 0:8918a71cdbe9 | 943 | #endif |
Sergunb | 0:8918a71cdbe9 | 944 |