A simple library to support serving https.
Dependents: oldheating gps motorhome heating
pki/pri-key.c@12:2c342345b3db, 2019-09-26 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Sep 26 07:19:09 2019 +0000
- Revision:
- 12:2c342345b3db
- Parent:
- 10:e269fd7b9500
- Child:
- 14:03a0b8fd6ddc
Chinese remainder theorem implemented giving a useful reduction from 20s to 5s to decrypt RSA.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 4:6a1d887f1cad | 1 | #include <stdint.h> |
andrewboyson | 4:6a1d887f1cad | 2 | |
andrewboyson | 0:be515c9019e3 | 3 | #include "base64.h" |
andrewboyson | 0:be515c9019e3 | 4 | #include "log.h" |
andrewboyson | 10:e269fd7b9500 | 5 | #include "rsa.h" |
andrewboyson | 0:be515c9019e3 | 6 | |
andrewboyson | 0:be515c9019e3 | 7 | /* |
andrewboyson | 0:be515c9019e3 | 8 | RSAPrivateKey ::= SEQUENCE { |
andrewboyson | 0:be515c9019e3 | 9 | version INTEGER, |
andrewboyson | 0:be515c9019e3 | 10 | modulus INTEGER, -- n |
andrewboyson | 0:be515c9019e3 | 11 | publicExponent INTEGER, -- e |
andrewboyson | 0:be515c9019e3 | 12 | privateExponent INTEGER, -- d |
andrewboyson | 0:be515c9019e3 | 13 | prime1 INTEGER, -- p |
andrewboyson | 0:be515c9019e3 | 14 | prime2 INTEGER, -- q |
andrewboyson | 0:be515c9019e3 | 15 | exponent1 INTEGER, -- d mod (p-1) |
andrewboyson | 0:be515c9019e3 | 16 | exponent2 INTEGER, -- d mod (q-1) |
andrewboyson | 0:be515c9019e3 | 17 | coefficient INTEGER, -- (inverse of q) mod p |
andrewboyson | 0:be515c9019e3 | 18 | otherPrimeInfos OtherPrimeInfos OPTIONAL |
andrewboyson | 0:be515c9019e3 | 19 | */ |
andrewboyson | 0:be515c9019e3 | 20 | |
andrewboyson | 4:6a1d887f1cad | 21 | uint8_t v [ 4]; //version |
andrewboyson | 4:6a1d887f1cad | 22 | uint8_t n [128]; //modulus |
andrewboyson | 4:6a1d887f1cad | 23 | uint8_t e [ 4]; //publicExponent |
andrewboyson | 4:6a1d887f1cad | 24 | uint8_t d [128]; //privateExponent |
andrewboyson | 4:6a1d887f1cad | 25 | uint8_t p [ 64]; //prime1 |
andrewboyson | 4:6a1d887f1cad | 26 | uint8_t q [ 64]; //prime2 |
andrewboyson | 4:6a1d887f1cad | 27 | uint8_t dp [ 64]; //exponent1 -- d mod (p-1) |
andrewboyson | 4:6a1d887f1cad | 28 | uint8_t dq [ 64]; //exponent2 -- d mod (q-1) |
andrewboyson | 4:6a1d887f1cad | 29 | uint8_t invq[ 64]; //coefficient -- (inverse of q) mod p |
andrewboyson | 0:be515c9019e3 | 30 | |
andrewboyson | 0:be515c9019e3 | 31 | static const char* pNext; |
andrewboyson | 0:be515c9019e3 | 32 | static const char* buffer = |
andrewboyson | 0:be515c9019e3 | 33 | #include "pri-key.inc" |
andrewboyson | 0:be515c9019e3 | 34 | ; |
andrewboyson | 0:be515c9019e3 | 35 | static char readChar() |
andrewboyson | 0:be515c9019e3 | 36 | { |
andrewboyson | 0:be515c9019e3 | 37 | char c = *pNext; |
andrewboyson | 0:be515c9019e3 | 38 | if (!c) return 0; |
andrewboyson | 0:be515c9019e3 | 39 | pNext++; |
andrewboyson | 0:be515c9019e3 | 40 | return c; |
andrewboyson | 0:be515c9019e3 | 41 | } |
andrewboyson | 0:be515c9019e3 | 42 | static int readLength() |
andrewboyson | 0:be515c9019e3 | 43 | { |
andrewboyson | 0:be515c9019e3 | 44 | int c = Base64ReadByte(); |
andrewboyson | 0:be515c9019e3 | 45 | if (c == -1) return -1; //EOF or an error |
andrewboyson | 0:be515c9019e3 | 46 | if (c < 0x80) return c; //Single byte length |
andrewboyson | 0:be515c9019e3 | 47 | if (c == 0x80) return -1; //indefinite form - do not use |
andrewboyson | 0:be515c9019e3 | 48 | int numberOfBytes = c - 0x80; |
andrewboyson | 0:be515c9019e3 | 49 | int len = 0; |
andrewboyson | 0:be515c9019e3 | 50 | for (int i = 0; i < numberOfBytes; i++) |
andrewboyson | 0:be515c9019e3 | 51 | { |
andrewboyson | 0:be515c9019e3 | 52 | len <<= 8; |
andrewboyson | 0:be515c9019e3 | 53 | c = Base64ReadByte(); |
andrewboyson | 0:be515c9019e3 | 54 | if (c == -1) return -1; //EOF or an error |
andrewboyson | 0:be515c9019e3 | 55 | len |= c; |
andrewboyson | 0:be515c9019e3 | 56 | } |
andrewboyson | 0:be515c9019e3 | 57 | return len; |
andrewboyson | 0:be515c9019e3 | 58 | } |
andrewboyson | 0:be515c9019e3 | 59 | static int readSequence() |
andrewboyson | 0:be515c9019e3 | 60 | { |
andrewboyson | 0:be515c9019e3 | 61 | int c = Base64ReadByte(); |
andrewboyson | 0:be515c9019e3 | 62 | if (c == -1) return -1; //EOF or an error |
andrewboyson | 0:be515c9019e3 | 63 | if (c != 0x30) return -1; //Not SEQUENCE type |
andrewboyson | 0:be515c9019e3 | 64 | int len = readLength(); |
andrewboyson | 0:be515c9019e3 | 65 | return len; |
andrewboyson | 0:be515c9019e3 | 66 | } |
andrewboyson | 4:6a1d887f1cad | 67 | static int readData(uint8_t* data, int size) //Reads the data from big-endian 'pem' format into little-endian 'bn' format |
andrewboyson | 0:be515c9019e3 | 68 | { |
andrewboyson | 0:be515c9019e3 | 69 | int c = Base64ReadByte(); |
andrewboyson | 0:be515c9019e3 | 70 | if (c == -1) return -1; //EOF or an error |
andrewboyson | 0:be515c9019e3 | 71 | if (c != 0x02) return -1; //Not INTEGER type |
andrewboyson | 0:be515c9019e3 | 72 | int pemLength = readLength(); |
andrewboyson | 0:be515c9019e3 | 73 | if (pemLength == -1) return -1; //EOF or an error |
andrewboyson | 0:be515c9019e3 | 74 | |
andrewboyson | 0:be515c9019e3 | 75 | int finalLength = pemLength; |
andrewboyson | 0:be515c9019e3 | 76 | for (int i = 0; i < pemLength; i++) |
andrewboyson | 0:be515c9019e3 | 77 | { |
andrewboyson | 0:be515c9019e3 | 78 | c = Base64ReadByte(); |
andrewboyson | 0:be515c9019e3 | 79 | if (c == -1) return -1; //EOF or an error |
andrewboyson | 0:be515c9019e3 | 80 | if (!i && !c) //Don't add if this is the msb and that byte is zero but reduce the final length by 1 |
andrewboyson | 0:be515c9019e3 | 81 | { |
andrewboyson | 0:be515c9019e3 | 82 | finalLength--; |
andrewboyson | 0:be515c9019e3 | 83 | } |
andrewboyson | 0:be515c9019e3 | 84 | else |
andrewboyson | 0:be515c9019e3 | 85 | { |
andrewboyson | 0:be515c9019e3 | 86 | data[pemLength - 1 - i] = c; //If pemLength is one too big then 'i' will also be one too big so the result is correct |
andrewboyson | 0:be515c9019e3 | 87 | } |
andrewboyson | 0:be515c9019e3 | 88 | } |
andrewboyson | 0:be515c9019e3 | 89 | for (int i = finalLength; i < size; i++) data[i] = 0; |
andrewboyson | 0:be515c9019e3 | 90 | |
andrewboyson | 0:be515c9019e3 | 91 | return finalLength + 1; |
andrewboyson | 0:be515c9019e3 | 92 | } |
andrewboyson | 0:be515c9019e3 | 93 | void PriKeyInit() |
andrewboyson | 0:be515c9019e3 | 94 | { |
andrewboyson | 0:be515c9019e3 | 95 | pNext = buffer; |
andrewboyson | 0:be515c9019e3 | 96 | Base64ReadNextCharFunctionPointer = readChar; |
andrewboyson | 0:be515c9019e3 | 97 | |
andrewboyson | 0:be515c9019e3 | 98 | int r = 0; |
andrewboyson | 0:be515c9019e3 | 99 | r = Base64SkipLine(); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 100 | r = readSequence(); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 101 | |
andrewboyson | 0:be515c9019e3 | 102 | r = readData( v, sizeof( v)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 103 | r = readData( n, sizeof( n)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 104 | r = readData( e, sizeof( e)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 105 | r = readData( d, sizeof( d)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 106 | r = readData( p, sizeof( p)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 107 | r = readData( q, sizeof( q)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 108 | r = readData( dp, sizeof( dp)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 109 | r = readData( dq, sizeof( dq)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 110 | r = readData(invq, sizeof(invq)); if (r < 0) return; |
andrewboyson | 0:be515c9019e3 | 111 | |
andrewboyson | 0:be515c9019e3 | 112 | Log("Primary key content\r\n"); |
andrewboyson | 0:be515c9019e3 | 113 | LogBytesAsHex( v, sizeof( v)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 114 | LogBytesAsHex( n, sizeof( n)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 115 | LogBytesAsHex( e, sizeof( e)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 116 | LogBytesAsHex( d, sizeof( d)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 117 | LogBytesAsHex( p, sizeof( p)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 118 | LogBytesAsHex( q, sizeof( q)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 119 | LogBytesAsHex( dp, sizeof( dp)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 120 | LogBytesAsHex( dq, sizeof( dq)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 121 | LogBytesAsHex(invq, sizeof(invq)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 122 | } |
andrewboyson | 4:6a1d887f1cad | 123 | int PriKeyDecryptStart(uint8_t* message) //return the slot number for the decryption |
andrewboyson | 0:be515c9019e3 | 124 | { |
andrewboyson | 1:9c66a551a67e | 125 | //Convert message to big number (little endian) format prior to decryption |
andrewboyson | 4:6a1d887f1cad | 126 | uint8_t leMessage[128]; |
andrewboyson | 1:9c66a551a67e | 127 | for (int i = 0; i < 128; i++) leMessage[127 - i] = message[i]; |
andrewboyson | 12:2c342345b3db | 128 | //return RsaSlowStart((uint32_t*)leMessage, (uint32_t*)d, (uint32_t*)n); |
andrewboyson | 12:2c342345b3db | 129 | return RsaFastStart((uint32_t*)leMessage, (uint32_t*)p, (uint32_t*)q, (uint32_t*)dp, (uint32_t*)dq, (uint32_t*)invq); |
andrewboyson | 2:82268409e83f | 130 | } |
andrewboyson | 2:82268409e83f | 131 | bool PriKeyDecryptFinished(int slot) |
andrewboyson | 2:82268409e83f | 132 | { |
andrewboyson | 12:2c342345b3db | 133 | //return RsaSlowFinished(slot); |
andrewboyson | 12:2c342345b3db | 134 | return RsaFastFinished(slot); |
andrewboyson | 0:be515c9019e3 | 135 | } |
andrewboyson | 4:6a1d887f1cad | 136 | uint8_t* PriKeyDecryptGetResult(int slot) |
andrewboyson | 0:be515c9019e3 | 137 | { |
andrewboyson | 12:2c342345b3db | 138 | //return (uint8_t*) RsaSlowResult(slot); |
andrewboyson | 12:2c342345b3db | 139 | return (uint8_t*) RsaFastResult(slot); |
andrewboyson | 2:82268409e83f | 140 | } |
andrewboyson | 2:82268409e83f | 141 | void PriKeyDecryptClear(int slot) |
andrewboyson | 2:82268409e83f | 142 | { |
andrewboyson | 12:2c342345b3db | 143 | //RsaSlowClear(slot); |
andrewboyson | 12:2c342345b3db | 144 | RsaFastClear(slot); |
andrewboyson | 12:2c342345b3db | 145 | } |
andrewboyson | 12:2c342345b3db | 146 | int PriKeyFastStart(uint8_t* message) //return the slot number for the decryption |
andrewboyson | 12:2c342345b3db | 147 | { |
andrewboyson | 12:2c342345b3db | 148 | //Convert message to big number (little endian) format prior to decryption |
andrewboyson | 12:2c342345b3db | 149 | uint8_t leMessage[128]; |
andrewboyson | 12:2c342345b3db | 150 | for (int i = 0; i < 128; i++) leMessage[127 - i] = message[i]; |
andrewboyson | 12:2c342345b3db | 151 | return RsaFastStart((uint32_t*)leMessage, (uint32_t*)p, (uint32_t*)q, (uint32_t*)dp, (uint32_t*)dq, (uint32_t*)invq); |
andrewboyson | 12:2c342345b3db | 152 | } |
andrewboyson | 12:2c342345b3db | 153 | bool PriKeyFastFinished(int slot) |
andrewboyson | 12:2c342345b3db | 154 | { |
andrewboyson | 12:2c342345b3db | 155 | return RsaFastFinished(slot); |
andrewboyson | 12:2c342345b3db | 156 | } |
andrewboyson | 12:2c342345b3db | 157 | uint8_t* PriKeyFastGetResult(int slot) |
andrewboyson | 12:2c342345b3db | 158 | { |
andrewboyson | 12:2c342345b3db | 159 | return (uint8_t*) RsaFastResult(slot); |
andrewboyson | 12:2c342345b3db | 160 | } |
andrewboyson | 12:2c342345b3db | 161 | void PriKeyFastClear(int slot) |
andrewboyson | 12:2c342345b3db | 162 | { |
andrewboyson | 12:2c342345b3db | 163 | RsaFastClear(slot); |
andrewboyson | 0:be515c9019e3 | 164 | } |