A simple library to support serving https.
Dependents: oldheating gps motorhome heating
pki/pri-key.c@24:cb43290fc439, 2020-04-01 (annotated)
- Committer:
- andrewboyson
- Date:
- Wed Apr 01 12:48:52 2020 +0000
- Revision:
- 24:cb43290fc439
- Parent:
- 21:a6d6e26dd742
Added check so that if the client closes the TCP connection before the TLS connection is established then respond that we have finished and the TCP connection is to be closed.
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 | 21:a6d6e26dd742 | 112 | /* |
andrewboyson | 0:be515c9019e3 | 113 | Log("Primary key content\r\n"); |
andrewboyson | 0:be515c9019e3 | 114 | LogBytesAsHex( v, sizeof( v)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 115 | LogBytesAsHex( n, sizeof( n)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 116 | LogBytesAsHex( e, sizeof( e)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 117 | LogBytesAsHex( d, sizeof( d)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 118 | LogBytesAsHex( p, sizeof( p)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 119 | LogBytesAsHex( q, sizeof( q)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 120 | LogBytesAsHex( dp, sizeof( dp)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 121 | LogBytesAsHex( dq, sizeof( dq)); Log("\n\n"); |
andrewboyson | 0:be515c9019e3 | 122 | LogBytesAsHex(invq, sizeof(invq)); Log("\n\n"); |
andrewboyson | 21:a6d6e26dd742 | 123 | */ |
andrewboyson | 0:be515c9019e3 | 124 | } |
andrewboyson | 4:6a1d887f1cad | 125 | int PriKeyDecryptStart(uint8_t* message) //return the slot number for the decryption |
andrewboyson | 0:be515c9019e3 | 126 | { |
andrewboyson | 1:9c66a551a67e | 127 | //Convert message to big number (little endian) format prior to decryption |
andrewboyson | 4:6a1d887f1cad | 128 | uint8_t leMessage[128]; |
andrewboyson | 1:9c66a551a67e | 129 | for (int i = 0; i < 128; i++) leMessage[127 - i] = message[i]; |
andrewboyson | 14:03a0b8fd6ddc | 130 | return RsaStart((uint32_t*)leMessage, (uint32_t*)p, (uint32_t*)q, (uint32_t*)dp, (uint32_t*)dq, (uint32_t*)invq); |
andrewboyson | 2:82268409e83f | 131 | } |
andrewboyson | 2:82268409e83f | 132 | bool PriKeyDecryptFinished(int slot) |
andrewboyson | 2:82268409e83f | 133 | { |
andrewboyson | 14:03a0b8fd6ddc | 134 | return RsaFinished(slot); |
andrewboyson | 0:be515c9019e3 | 135 | } |
andrewboyson | 17:93feb2a51d58 | 136 | uint8_t* PriKeyDecryptResultLittleEndian(int slot) |
andrewboyson | 0:be515c9019e3 | 137 | { |
andrewboyson | 14:03a0b8fd6ddc | 138 | return (uint8_t*) RsaResult(slot); |
andrewboyson | 2:82268409e83f | 139 | } |
andrewboyson | 17:93feb2a51d58 | 140 | void PriKeyDecryptResultTail(int slot, int length, uint8_t* pBuffer) |
andrewboyson | 17:93feb2a51d58 | 141 | { |
andrewboyson | 17:93feb2a51d58 | 142 | //Convert result from big number (little endian) format after decryption |
andrewboyson | 17:93feb2a51d58 | 143 | uint8_t* pLittleEndian = (uint8_t*) RsaResult(slot); |
andrewboyson | 17:93feb2a51d58 | 144 | for (int i = 0; i < length; i++) *(pBuffer + i) = *(pLittleEndian + length - 1 - i); |
andrewboyson | 17:93feb2a51d58 | 145 | } |
andrewboyson | 2:82268409e83f | 146 | void PriKeyDecryptClear(int slot) |
andrewboyson | 2:82268409e83f | 147 | { |
andrewboyson | 14:03a0b8fd6ddc | 148 | RsaClear(slot); |
andrewboyson | 0:be515c9019e3 | 149 | } |