Line data Source code
1 : /** 2 : * The MIT License (MIT) 3 : * 4 : * Copyright (c) 2021 RSK Labs Ltd 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 8 : * deal in the Software without restriction, including without limitation the 9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 : * sell 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 14 : * all 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 21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 : * IN THE SOFTWARE. 23 : */ 24 : 25 : #include "der_utils.h" 26 : #include <stddef.h> 27 : #include <stdbool.h> 28 : #include <string.h> 29 : 30 : // Helper function to encode a len-byte unsigned integer (R or S) in DER format 31 28 : static size_t der_encode_uint(uint8_t* dest, uint8_t* src, size_t len) { 32 : // Check if we need a leading zero byte 33 28 : bool lz = src[0] & 0x80; 34 : // Start of source: remove leading zeroes 35 28 : size_t trim = 0; 36 226 : while (!src[trim] && trim < (len - 1)) 37 198 : trim++; 38 : // Output 39 28 : size_t off = 0; 40 28 : dest[off++] = 0x02; // Integer tag 41 28 : dest[off++] = len - trim + (lz ? 1 : 0); // Length byte 42 28 : if (lz) 43 6 : dest[off++] = 0x00; // Leading zero 44 28 : memcpy(dest + off, src + trim, len - trim); // Actual integer 45 28 : return (size_t)dest[1] + 2; 46 : } 47 : 48 14 : uint8_t der_encode_signature(uint8_t* dest, 49 : size_t dest_size, 50 : sgx_ecdsa256_signature_t* sig) { 51 : // Temporary buffers for R and S with 52 : // space for TLV with potential leading zero 53 : uint8_t r_encoded[sizeof(sig->r) + 3]; 54 : uint8_t s_encoded[sizeof(sig->r) + 3]; 55 14 : uint8_t r_len = (uint8_t)der_encode_uint(r_encoded, sig->r, sizeof(sig->r)); 56 14 : uint8_t s_len = (uint8_t)der_encode_uint(s_encoded, sig->s, sizeof(sig->s)); 57 : 58 : // Check for enough space in destination buffer 59 14 : if (dest_size < (size_t)(r_len + s_len + 2)) 60 7 : return 0; 61 : 62 : // Start the sequence 63 7 : dest[0] = 0x30; // Sequence tag 64 7 : dest[1] = r_len + s_len; // Length of the sequence 65 7 : memcpy(dest + 2, r_encoded, r_len); // Copy encoded R 66 7 : memcpy(dest + 2 + r_len, s_encoded, s_len); // Copy encoded S 67 : 68 : // Return total length of DER encoded signature 69 7 : return (uint8_t)(2 + r_len + s_len); 70 : }