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.dup;
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 }