ecdsa_utils.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /**
  2. * MIT License
  3. *
  4. * Copyright (c) 2019 Infineon Technologies AG
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE
  23. *
  24. *
  25. * \file ecdsa_utils.c
  26. *
  27. * \brief This file provides functions to convert raw r and s components of the ECDSA signature to asn1 encoding
  28. *
  29. *
  30. * \addtogroup grOptigaUtil
  31. * @{
  32. */
  33. #include "ecdsa_utils.h"
  34. #include <string.h>
  35. // This implementation only supports a single byte LENGTH field. The maximum
  36. // possible value than can be encoded within a single byte is 0x7F (127 dec).
  37. // For higher values, the length must be coded in a multi-byte field.
  38. #define DER_INTEGER_MAX_LEN 0x7F
  39. // This implementation only supports a single byte LENGTH field. The maximum
  40. // possible value than can be encoded within a single byte is 0x7F (127 dec).
  41. // For higher values, the length must be coded in a multi-byte field.
  42. #define DER_SEQUENCE_MAX_LEN 0x7F
  43. // ASN.1 DER TAG field offset
  44. #define ASN1_DER_TAG_OFFSET 0
  45. // ASN.1 DER LENGTH field offset
  46. #define ASN1_DER_LEN_OFFSET 1
  47. // ASN.1 DER VALUE field offset
  48. // Only for this implementation!
  49. #define ASN1_DER_VAL_OFFSET 2
  50. // ASN.1 DER Tag for INTEGER
  51. #define DER_TAG_INTEGER 0x02
  52. // ASN.1 DER Tag for SEQUENCE
  53. #define DER_TAG_SEQUENCE 0x30
  54. #define DER_UINT_MASK 0x80
  55. /**
  56. * @brief Encodes a byte buffer as unsigned ASN.1 DER INTEGER
  57. *
  58. * @param data[in] Buffer containing the bytes to be encoded
  59. * @param data_len[in] Length of the data buffer
  60. * @param out_buf[out] Output buffer for the encoded ASN.1 bytes
  61. * @param out_buf_len[in] Size of the out_buf buffer
  62. * @return The number of bytes of the ASN.1 encoded stream on success, 0 on error
  63. * @note The parameters to this function must not be NULL.
  64. */
  65. static size_t encode_der_integer(const uint8_t* data, size_t data_len,
  66. uint8_t* out_buf, size_t out_buf_len)
  67. {
  68. // all write access must be smaller or equal to this pointer
  69. const uint8_t* const out_end = out_buf + out_buf_len - 1;
  70. // fixed position fields
  71. uint8_t* const tag_field = &out_buf[ASN1_DER_TAG_OFFSET];
  72. uint8_t* const length_field = &out_buf[ASN1_DER_LEN_OFFSET];
  73. uint8_t* const integer_field_start = &out_buf[ASN1_DER_VAL_OFFSET];
  74. // write pointer
  75. uint8_t* integer_field_cur = integer_field_start;
  76. // search for beginning of integer
  77. const uint8_t* cur_data = data;
  78. const uint8_t* const data_end = data + data_len;
  79. // check if something to encode, else next loop condition overflows
  80. if (data_len == 0) {
  81. return 0;
  82. }
  83. // don't check the last byte, it will always be a data byte
  84. for(; cur_data < (data_end - 1); cur_data++) {
  85. if (*cur_data != 0x00) {
  86. break;
  87. }
  88. }
  89. // check if stuffing byte needed
  90. if (*cur_data & DER_UINT_MASK) {
  91. integer_field_cur++;
  92. }
  93. // calculate number of bytes left in data
  94. const size_t write_length = data_end - cur_data;
  95. // check if it fits in the output buffer
  96. if ((integer_field_cur + write_length - 1) > out_end) {
  97. // Prevented out-of-bounds write
  98. return 0;
  99. }
  100. // ensure we can encode the length
  101. const size_t integer_len = (integer_field_cur + write_length) - integer_field_start;
  102. if (integer_len > DER_INTEGER_MAX_LEN) {
  103. // This implementation support single-byte LENGTH fields only
  104. return 0;
  105. }
  106. // commit writes
  107. memcpy(integer_field_cur, cur_data, write_length);
  108. *tag_field = DER_TAG_INTEGER;
  109. *length_field = integer_len;
  110. // check if we have a stuffing byte, and explicitly zero it
  111. if (integer_field_cur != integer_field_start) {
  112. *integer_field_start = 0x00;
  113. }
  114. return integer_len + ASN1_DER_VAL_OFFSET;
  115. }
  116. bool ecdsa_rs_to_asn1_integers(const uint8_t* r, const uint8_t* s, size_t rs_len,
  117. uint8_t* asn_sig, size_t* asn_sig_len)
  118. {
  119. if (r == NULL || s == NULL || asn_sig == NULL || asn_sig_len == NULL) {
  120. // No NULL paramters allowed
  121. return false;
  122. }
  123. // encode R component
  124. const size_t out_len_r = encode_der_integer(r, rs_len, asn_sig, *asn_sig_len);
  125. if (out_len_r == 0) {
  126. // error while encoding R as DER INTEGER
  127. return false;
  128. }
  129. uint8_t* const s_start = asn_sig + out_len_r;
  130. const size_t s_len = *asn_sig_len - out_len_r;
  131. // encode S component
  132. const size_t out_len_s = encode_der_integer(s, rs_len, s_start, s_len);
  133. if (out_len_s == 0) {
  134. // error while encoding S as DER INTEGER
  135. return false;
  136. }
  137. *asn_sig_len = out_len_r + out_len_s;
  138. return true;
  139. }
  140. bool ecdsa_rs_to_asn1_signature(const uint8_t* r, const uint8_t* s, size_t rs_len,
  141. uint8_t* asn_sig, size_t* asn_sig_len)
  142. {
  143. if (r == NULL || s == NULL || asn_sig == NULL || asn_sig_len == NULL) {
  144. // No NULL paramters allowed
  145. return false;
  146. }
  147. if (*asn_sig_len < ASN1_DER_VAL_OFFSET) {
  148. // Not enough space, can't encode anything
  149. return false;
  150. }
  151. // fixed position fields
  152. uint8_t* const tag_field = &asn_sig[ASN1_DER_TAG_OFFSET];
  153. uint8_t* const length_field = &asn_sig[ASN1_DER_LEN_OFFSET];
  154. uint8_t* const value_field_start = &asn_sig[ASN1_DER_VAL_OFFSET];
  155. // compute size left after SEQUENCE header TAG and LENGTH fields
  156. size_t integers_len = *asn_sig_len - ASN1_DER_VAL_OFFSET;
  157. if (!ecdsa_rs_to_asn1_integers(r, s, rs_len, value_field_start, &integers_len)) {
  158. // Failed to encode R and S as INTEGERs
  159. return false;
  160. }
  161. if (integers_len > DER_SEQUENCE_MAX_LEN) {
  162. // This implementation support single-byte LENGTH fields only
  163. return false;
  164. }
  165. // write SEQUENCE header
  166. *tag_field = DER_TAG_SEQUENCE;
  167. *length_field = integers_len;
  168. *asn_sig_len = integers_len + ASN1_DER_VAL_OFFSET;
  169. return true;
  170. }
  171. /**
  172. * @brief Decodes an ASN.1 encoded integer to a byte buffer
  173. *
  174. * @param asn1[in] Buffer containing the ASN.1 encoded data
  175. * @param asn1_len[in] Length of the asn1 buffer
  176. * @param out_int[out] Output buffer for the decoded integer bytes
  177. * @param out_int_len[in,out] Size of the out_int buffer, contains the number of written bytes afterwards
  178. * @return The number of bytes advanced in the ASN.1 stream on success, 0 on failure
  179. * @note The parameters to this function must not be NULL.
  180. */
  181. static size_t decode_asn1_uint(const uint8_t* asn1, size_t asn1_len,
  182. uint8_t* out_int, size_t* out_int_len)
  183. {
  184. if (asn1_len < (ASN1_DER_VAL_OFFSET + 1)) {
  185. // Not enough data to decode anything
  186. return 0;
  187. }
  188. // all read access must be before this pointer
  189. const uint8_t* const asn1_end = asn1 + asn1_len;
  190. // fixed position fields
  191. const uint8_t* const tag_field = &asn1[ASN1_DER_TAG_OFFSET];
  192. const uint8_t* const length_field = &asn1[ASN1_DER_LEN_OFFSET];
  193. if (*tag_field != DER_TAG_INTEGER) {
  194. // Not an DER INTEGER
  195. return 0;
  196. }
  197. if (*length_field == 0 || *length_field > DER_INTEGER_MAX_LEN) {
  198. // Invalid length value
  199. return 0;
  200. }
  201. uint8_t integer_length = *length_field;
  202. const uint8_t* integer_field_cur = &asn1[ASN1_DER_VAL_OFFSET];
  203. if ((integer_field_cur + integer_length - 1) > (asn1_end - 1)) {
  204. // prevented out-of-bounds read
  205. return 0;
  206. }
  207. // one byte can never be a stuffing byte
  208. if (integer_length > 1) {
  209. if (*integer_field_cur == 0x00) {
  210. // remove stuffing byte
  211. integer_length--;
  212. integer_field_cur++;
  213. }
  214. if (*integer_field_cur == 0x00) {
  215. // second zero byte is an encoding error
  216. return 0;
  217. }
  218. }
  219. if (integer_length > *out_int_len) {
  220. // prevented out-of-bounds write
  221. return 0;
  222. }
  223. // insert padding zeros to ensure position of least significant byte matches
  224. const size_t padding = *out_int_len - integer_length;
  225. memset(out_int, 0, padding);
  226. memcpy(out_int + padding, integer_field_cur, integer_length);
  227. *out_int_len = integer_length;
  228. // return number of consumed ASN.1 bytes
  229. return integer_field_cur + integer_length - tag_field;
  230. }
  231. bool asn1_to_ecdsa_rs_sep(const uint8_t* asn1, size_t asn1_len,
  232. uint8_t* r, size_t* r_len,
  233. uint8_t* s, size_t* s_len)
  234. {
  235. if (asn1 == NULL || r == NULL || r_len == NULL || s == NULL || s_len == NULL) {
  236. // No NULL paramters allowed
  237. return false;
  238. }
  239. // decode R component
  240. const size_t consumed_r = decode_asn1_uint(asn1, asn1_len, r, r_len);
  241. if (consumed_r == 0) {
  242. // error while decoding R component
  243. return false;
  244. }
  245. const uint8_t* const asn1_s = asn1 + consumed_r;
  246. const size_t asn1_s_len = asn1_len - consumed_r;
  247. // decode S component
  248. const size_t consumed_s = decode_asn1_uint(asn1_s, asn1_s_len, s, s_len);
  249. if (consumed_s == 0) {
  250. // error while decoding R component
  251. return false;
  252. }
  253. return true;
  254. }
  255. bool asn1_to_ecdsa_rs(const uint8_t* asn1, size_t asn1_len,
  256. uint8_t* rs, size_t rs_len)
  257. {
  258. if (asn1 == NULL || rs == NULL || rs_len == 0) {
  259. // No NULL paramters allowed
  260. return false;
  261. }
  262. if ((rs_len % 2) != 0) {
  263. // length of the output buffer must be 2 times the component size and even
  264. return false;
  265. }
  266. const size_t component_length = rs_len / 2;
  267. size_t r_len = component_length;
  268. size_t s_len = component_length;
  269. return asn1_to_ecdsa_rs_sep(asn1, asn1_len, rs, &r_len, rs + component_length, &s_len);
  270. }