1 /** 2 * PKCS #1 v1.5 signature padding 3 * 4 * Copyright: 5 * (C) 1999-2008 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.pk_pad.emsa_pkcs1; 12 13 import botan.constants; 14 static if (BOTAN_HAS_EMSA_PKCS1): 15 16 import botan.pk_pad.emsa; 17 import botan.hash.hash; 18 import botan.pk_pad.emsa_pkcs1; 19 import botan.pk_pad.hash_id; 20 import botan.utils.types; 21 import botan.utils.mem_ops; 22 import std.algorithm : swap; 23 24 /** 25 * PKCS #1 v1.5 signature padding 26 * aka PKCS #1 block type 1 27 * aka EMSA3 from IEEE 1363 28 */ 29 final class EMSAPKCS1v15 : EMSA 30 { 31 public: 32 /** 33 * Params: 34 * hash = the hash object to use 35 */ 36 this(HashFunction hash) 37 { 38 m_hash = hash; 39 m_hash_id = pkcsHashId(m_hash.name); 40 } 41 42 override void update(const(ubyte)* input, size_t length) 43 { 44 m_hash.update(input, length); 45 } 46 47 override SecureVector!ubyte rawData() 48 { 49 return m_hash.finished(); 50 } 51 52 override SecureVector!ubyte 53 encodingOf(const ref SecureVector!ubyte msg, 54 size_t output_bits, 55 RandomNumberGenerator) 56 { 57 if (msg.length != m_hash.outputLength) 58 throw new EncodingError("encodingOf: Bad input length"); 59 60 return emsa3Encoding(msg, output_bits, 61 m_hash_id.ptr, m_hash_id.length); 62 } 63 64 override bool verify(const ref SecureVector!ubyte coded, 65 const ref SecureVector!ubyte raw, 66 size_t key_bits) 67 { 68 if (raw.length != m_hash.outputLength) 69 return false; 70 71 try 72 { 73 return (coded == emsa3Encoding(raw, key_bits, 74 m_hash_id.ptr, m_hash_id.length)); 75 } 76 catch (Exception) 77 { 78 return false; 79 } 80 } 81 private: 82 Unique!HashFunction m_hash; 83 Vector!ubyte m_hash_id; 84 } 85 86 /** 87 * EMSA_PKCS1v15_Raw which is EMSA_PKCS1v15 without a hash or digest id 88 * (which according to QCA docs is "identical to PKCS#11's CKM_RSA_PKCS 89 * mechanism", something I have not confirmed) 90 */ 91 final class EMSAPKCS1v15Raw : EMSA 92 { 93 public: 94 override void update(const(ubyte)* input, size_t length) 95 { 96 m_message ~= input[0 .. length]; 97 } 98 99 override SecureVector!ubyte rawData() 100 { 101 return m_message.clone; 102 } 103 104 override SecureVector!ubyte encodingOf(const ref SecureVector!ubyte msg, 105 size_t output_bits, 106 RandomNumberGenerator) 107 { 108 return emsa3Encoding(msg, output_bits, null, 0); 109 } 110 111 override bool verify(const ref SecureVector!ubyte coded, 112 const ref SecureVector!ubyte raw, 113 size_t key_bits) 114 { 115 try 116 { 117 return (coded == emsa3Encoding(raw, key_bits, null, 0)); 118 } 119 catch (Exception) 120 { 121 return false; 122 } 123 } 124 125 private: 126 SecureVector!ubyte m_message; 127 } 128 129 private: 130 131 SecureVector!ubyte emsa3Encoding(const ref SecureVector!ubyte msg, 132 size_t output_bits, 133 const(ubyte)* hash_id, 134 size_t hash_id_length) 135 { 136 size_t output_length = output_bits / 8; 137 if (output_length < hash_id_length + msg.length + 10) 138 throw new EncodingError("emsa3Encoding: Output length is too small"); 139 140 SecureVector!ubyte T = SecureVector!ubyte(output_length); 141 const size_t P_LENGTH = output_length - msg.length - hash_id_length - 2; 142 143 T[0] = 0x01; 144 setMem(&T[1], P_LENGTH, 0xFF); 145 T[P_LENGTH+1] = 0x00; 146 bufferInsert(T, P_LENGTH+2, hash_id, hash_id_length); 147 bufferInsert(T, output_length-msg.length, msg.ptr, msg.length); 148 return T; 149 }