A simple library to support serving https.
Dependents: oldheating gps motorhome heating
pki/pri-key.c@10:e269fd7b9500, 2019-09-24 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Sep 24 18:11:02 2019 +0000
- Revision:
- 10:e269fd7b9500
- Parent:
- 4:6a1d887f1cad
- Child:
- 12:2c342345b3db
Got padlock and some application data through. Now need to use China remainder theorem to speed up decryption and things up and the session id to avoid having to do the decryption.
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 | 10:e269fd7b9500 | 128 | return RsaSlowStart((uint32_t*)leMessage, (uint32_t*)d, (uint32_t*)n); |
andrewboyson | 2:82268409e83f | 129 | } |
andrewboyson | 2:82268409e83f | 130 | bool PriKeyDecryptFinished(int slot) |
andrewboyson | 2:82268409e83f | 131 | { |
andrewboyson | 10:e269fd7b9500 | 132 | return RsaSlowFinished(slot); |
andrewboyson | 0:be515c9019e3 | 133 | } |
andrewboyson | 4:6a1d887f1cad | 134 | uint8_t* PriKeyDecryptGetResult(int slot) |
andrewboyson | 0:be515c9019e3 | 135 | { |
andrewboyson | 10:e269fd7b9500 | 136 | return (uint8_t*) RsaSlowResult(slot); |
andrewboyson | 2:82268409e83f | 137 | } |
andrewboyson | 2:82268409e83f | 138 | void PriKeyDecryptClear(int slot) |
andrewboyson | 2:82268409e83f | 139 | { |
andrewboyson | 10:e269fd7b9500 | 140 | RsaSlowClear(slot); |
andrewboyson | 0:be515c9019e3 | 141 | } |