Codebase list dnsviz / 7dd833a
Merge branch 'master' of github.com:dnsviz/dnsviz Casey Deccio 8 years ago
7 changed file(s) with 781 addition(s) and 253 deletion(s). Raw diff Collapse all Expand all
3737 Note that support for the following DNSSEC algorithms is not yet available in
3838 stock releases of M2Crypto: 3 (DSA-SHA1), 6 (DSA-NSEC3-SHA1),
3939 12 (GOST R 34.10-2001), 13 (ECDSA Curve P-256 with SHA-256), 14 (ECDSA Curve
40 P-384 with SHA-384). However, the patch included in "contrib/m2crypto.patch"
41 can be applied to M2Crypto 0.21.1 or M2Crypto 0.22.3 to support these
42 algorithms:
40 P-384 with SHA-384). However, there are two patches included in the
41 `contrib` directory that can be applied to M2Crypto 0.21.1, M2Crypto 0.22.3
42 (`config/m2crypto-pre0.26.patch`), or M2Crypto 0.26
43 (`config/m2crypto-0.26.patch`). For example:
4344
4445 ```
45 $ patch -p1 < /path/to/dnsviz-source/contrib/m2crypto.patch
46 $ patch -p1 < /path/to/dnsviz-source/contrib/m2crypto-pre0.26.patch
4647 ```
4748
4849 ### Build and Install
0 diff --git a/M2Crypto/DSA.py b/M2Crypto/DSA.py
1 index 57d123b..325e418 100644
2 --- a/M2Crypto/DSA.py
3 +++ b/M2Crypto/DSA.py
4 @@ -396,6 +396,29 @@ def load_key_bio(bio, callback=util.passphrase_callback):
5 raise DSAError('problem loading DSA key pair')
6 return DSA(dsa, 1)
7
8 +def pub_key_from_params(p, q, g, pub):
9 + """
10 + Factory function that instantiates a DSA_pub object using
11 + the parameters and public key specified.
12 +
13 + @type p: str
14 + @param p: value of p, a "byte string"
15 + @type q: str
16 + @param q: value of q, a "byte string"
17 + @type g: str
18 + @param g: value of g, a "byte string"
19 + @type pub: str
20 + @param pub: value of the public key, a "byte string"
21 + @rtype: DSA_pub
22 + @return: instance of DSA_pub.
23 + """
24 + dsa = m2.dsa_new()
25 + m2.dsa_set_p(dsa, p)
26 + m2.dsa_set_q(dsa, q)
27 + m2.dsa_set_g(dsa, g)
28 + m2.dsa_set_pub(dsa, pub)
29 + return DSA_pub(dsa, 1)
30 +
31
32 def load_pub_key(file, callback=util.passphrase_callback):
33 """
34 diff --git a/M2Crypto/EC.py b/M2Crypto/EC.py
35 index a4a9faf..800a705 100644
36 --- a/M2Crypto/EC.py
37 +++ b/M2Crypto/EC.py
38 @@ -254,6 +254,13 @@ class EC_pub(EC):
39 self.der = m2.ec_key_get_public_der(self.ec)
40 return self.der
41
42 + def get_key(self):
43 + """
44 + Returns the public key as a byte string.
45 + """
46 + assert self.check_key(), 'key is not initialised'
47 + return m2.ec_key_get_public_key(self.ec)
48 +
49 save_key = EC.save_pub_key
50
51 save_key_bio = EC.save_pub_key_bio
52 @@ -333,3 +340,9 @@ def pub_key_from_der(der):
53 Create EC_pub from DER.
54 """
55 return EC_pub(m2.ec_key_from_pubkey_der(der), 1)
56 +
57 +def pub_key_from_params(curve, bytes):
58 + """
59 + Create EC_pub from curve name and octet string.
60 + """
61 + return EC_pub(m2.ec_key_from_pubkey_params(curve, bytes), 1)
62 diff --git a/M2Crypto/EVP.py b/M2Crypto/EVP.py
63 index 12618a2..28303bd 100644
64 --- a/M2Crypto/EVP.py
65 +++ b/M2Crypto/EVP.py
66 @@ -40,8 +40,13 @@ class MessageDigest:
67 def __init__(self, algo):
68 md = getattr(m2, algo, None)
69 if md is None:
70 - raise ValueError('unknown algorithm', algo)
71 - self.md = md()
72 + # if the digest algorithm isn't found as an attribute of the m2
73 + # module, try to look up the digest using get_digestbyname()
74 + self.md = m2.get_digestbyname(algo)
75 + if self.md is None:
76 + raise ValueError('unknown algorithm', algo)
77 + else:
78 + self.md = md()
79 self.ctx = m2.md_ctx_new()
80 m2.digest_init(self.ctx, self.md)
81
82 @@ -389,6 +394,25 @@ def load_key_bio(bio, callback=util.passphrase_callback):
83 raise EVPError(Err.get_error())
84 return PKey(cptr, 1)
85
86 +def load_key_bio_pubkey(bio, callback=util.passphrase_callback):
87 + """
88 + Load an M2Crypto.EVP.PKey from a public key as a M2Crypto.BIO object.
89 +
90 + @type bio: M2Crypto.BIO
91 + @param bio: M2Crypto.BIO object containing the key in PEM format.
92 +
93 + @type callback: Python callable
94 + @param callback: A Python callable object that is invoked
95 + to acquire a passphrase with which to protect the key.
96 +
97 + @rtype: M2Crypto.EVP.PKey
98 + @return: M2Crypto.EVP.PKey object.
99 + """
100 + cptr = m2.pkey_read_pem_pubkey(bio._ptr(), callback)
101 + if cptr is None:
102 + raise EVPError(Err.get_error())
103 + return PKey(cptr, 1)
104 +
105 def load_key_string(string, callback=util.passphrase_callback):
106 """
107 Load an M2Crypto.EVP.PKey from a string.
108 @@ -405,3 +429,20 @@ def load_key_string(string, callback=util.passphrase_callback):
109 """
110 bio = BIO.MemoryBuffer(string)
111 return load_key_bio(bio, callback)
112 +
113 +def load_key_string_pubkey(string, callback=util.passphrase_callback):
114 + """
115 + Load an M2Crypto.EVP.PKey from a public key as a string.
116 +
117 + @type string: string
118 + @param string: String containing the key in PEM format.
119 +
120 + @type callback: Python callable
121 + @param callback: A Python callable object that is invoked
122 + to acquire a passphrase with which to protect the key.
123 +
124 + @rtype: M2Crypto.EVP.PKey
125 + @return: M2Crypto.EVP.PKey object.
126 + """
127 + bio = BIO.MemoryBuffer(string)
128 + return load_key_bio_pubkey(bio, callback)
129 diff --git a/SWIG/_dsa.i b/SWIG/_dsa.i
130 index a35dd88..a6da42d 100644
131 --- a/SWIG/_dsa.i
132 +++ b/SWIG/_dsa.i
133 @@ -153,6 +153,25 @@ PyObject *dsa_set_g(DSA *dsa, PyObject *value) {
134 Py_INCREF(Py_None);
135 return Py_None;
136 }
137 +
138 +PyObject *dsa_set_pub(DSA *dsa, PyObject *value) {
139 + BIGNUM *bn;
140 + const void *vbuf;
141 + int vlen;
142 +
143 + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
144 + return NULL;
145 +
146 + if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) {
147 + PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error()));
148 + return NULL;
149 + }
150 + if (dsa->pub_key)
151 + BN_free(dsa->pub_key);
152 + dsa->pub_key = bn;
153 + Py_INCREF(Py_None);
154 + return Py_None;
155 +}
156 %}
157
158 %inline %{
159 diff --git a/SWIG/_ec.i b/SWIG/_ec.i
160 index f0e52bd..9065c10 100644
161 --- a/SWIG/_ec.i
162 +++ b/SWIG/_ec.i
163 @@ -189,6 +189,43 @@ PyObject *ec_key_get_public_der(EC_KEY *key) {
164
165 return pyo;
166 }
167 +
168 +PyObject *ec_key_get_public_key(EC_KEY *key) {
169 +
170 + unsigned char *src=NULL;
171 + void *dst=NULL;
172 + int src_len=0;
173 + Py_ssize_t dst_len=0;
174 + PyObject *pyo=NULL;
175 + int ret=0;
176 +
177 + /* Convert to binary */
178 + src_len = i2o_ECPublicKey(key, &src);
179 + if (src_len < 0)
180 + {
181 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
182 + return NULL;
183 + }
184 +
185 + /* Create a PyBuffer containing a copy of the binary,
186 + * to simplify memory deallocation
187 + */
188 + pyo = PyBuffer_New( src_len );
189 + ret = PyObject_AsWriteBuffer( pyo, &dst, &dst_len );
190 + assert( src_len == dst_len );
191 + if (ret < 0)
192 + {
193 + Py_DECREF(pyo);
194 + OPENSSL_free(src);
195 + PyErr_SetString(_ec_err, "cannot get write buffer");
196 + return NULL;
197 + }
198 + memcpy( dst, src, src_len );
199 + OPENSSL_free(src);
200 +
201 + return pyo;
202 +}
203 +
204 %}
205
206 %threadallow ec_key_read_pubkey;
207 @@ -404,6 +441,32 @@ EC_KEY* ec_key_from_pubkey_der(PyObject *pubkey) {
208 return keypair;
209 }
210
211 +EC_KEY* ec_key_from_pubkey_params(int nid, PyObject *pubkey) {
212 + const void *keypairbuf;
213 + Py_ssize_t keypairbuflen;
214 + const unsigned char *tempBuf;
215 + EC_KEY *keypair;
216 +
217 + if (PyObject_AsReadBuffer(pubkey, &keypairbuf, &keypairbuflen) == -1)
218 + {
219 + return NULL;
220 + }
221 +
222 + keypair = ec_key_new_by_curve_name(nid);
223 + if (!keypair) {
224 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
225 + return NULL;
226 + }
227 +
228 + tempBuf = (const unsigned char *)keypairbuf;
229 + if ((o2i_ECPublicKey( &keypair, &tempBuf, keypairbuflen)) == 0)
230 + {
231 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
232 + return NULL;
233 + }
234 + return keypair;
235 +}
236 +
237
238 // According to [SEC2] the degree of the group is defined as EC key length
239 int ec_key_keylen(EC_KEY *key) {
240 diff --git a/SWIG/_evp.i b/SWIG/_evp.i
241 index 85382db..033897b 100644
242 --- a/SWIG/_evp.i
243 +++ b/SWIG/_evp.i
244 @@ -49,6 +49,9 @@ extern const EVP_MD *EVP_sha512(void);
245 %rename(digest_init) EVP_DigestInit;
246 extern int EVP_DigestInit(EVP_MD_CTX *, const EVP_MD *);
247
248 +%rename(get_digestbyname) EVP_get_digestbyname;
249 +extern EVP_MD *EVP_get_digestbyname(const char * name);
250 +
251 %rename(des_ecb) EVP_des_ecb;
252 extern const EVP_CIPHER *EVP_des_ecb(void);
253 %rename(des_ede_ecb) EVP_des_ede;
254 @@ -519,6 +522,17 @@ EVP_PKEY *pkey_read_pem(BIO *f, PyObject *pyfunc) {
255 return pk;
256 }
257
258 +EVP_PKEY *pkey_read_pem_pubkey(BIO *f, PyObject *pyfunc) {
259 + EVP_PKEY *pk;
260 +
261 + Py_INCREF(pyfunc);
262 + Py_BEGIN_ALLOW_THREADS
263 + pk = PEM_read_bio_PUBKEY(f, NULL, passphrase_callback, (void *)pyfunc);
264 + Py_END_ALLOW_THREADS
265 + Py_DECREF(pyfunc);
266 + return pk;
267 +}
268 +
269 int pkey_assign_rsa(EVP_PKEY *pkey, RSA *rsa) {
270 return EVP_PKEY_assign_RSA(pkey, rsa);
271 }
272 diff --git a/tests/test_dsa.py b/tests/test_dsa.py
273 index 27d1f61..c224a53 100644
274 --- a/tests/test_dsa.py
275 +++ b/tests/test_dsa.py
276 @@ -99,6 +99,19 @@ class DSATestCase(unittest.TestCase):
277 r, s = dsa2.sign(self.data)
278 assert dsa2.verify(self.data, r, s)
279
280 + def test_pub_key_from_params(self):
281 + dsa = DSA.gen_params(1024, self.callback)
282 + dsa.gen_key()
283 + assert len(dsa) == 1024
284 + p = dsa.p
285 + q = dsa.q
286 + g = dsa.g
287 + pub = dsa.pub
288 + dsa2 = DSA.pub_key_from_params(p,q,g,pub)
289 + assert dsa2.check_key()
290 + r,s = dsa.sign(self.data)
291 + assert dsa2.verify(self.data, r, s)
292 +
293 def suite():
294 return unittest.makeSuite(DSATestCase)
295
296 diff --git a/tests/test_ecdsa.py b/tests/test_ecdsa.py
297 index d6c75d1..d28be96 100644
298 --- a/tests/test_ecdsa.py
299 +++ b/tests/test_ecdsa.py
300 @@ -70,6 +70,16 @@ class ECDSATestCase(unittest.TestCase):
301 ec = EC.gen_params(EC.NID_sect233k1)
302 self.assertEqual(len(ec), 233)
303
304 + def test_pub_key_from_params(self):
305 + curve = EC.NID_X9_62_prime256v1
306 + ec = EC.gen_params(curve)
307 + ec.gen_key()
308 + ec_pub = ec.pub()
309 + k = ec_pub.get_key()
310 + ec2 = EC.pub_key_from_params(curve, k)
311 + assert ec2.check_key()
312 + r, s = ec.sign_dsa(self.data)
313 + assert ec2.verify_dsa(self.data, r, s)
314
315 def suite():
316 return unittest.makeSuite(ECDSATestCase)
317 diff --git a/tests/test_evp.py b/tests/test_evp.py
318 index 8cf7d12..bddec84 100644
319 --- a/tests/test_evp.py
320 +++ b/tests/test_evp.py
321 @@ -58,6 +58,9 @@ class EVPTestCase(unittest.TestCase):
322 # A quick but not thorough sanity check
323 self.assertEqual(len(der_blob), 160)
324
325 + def test_get_digestbyname(self):
326 + self.assertEqual(m2.get_digestbyname('sha513'), None)
327 + self.assertNotEqual(m2.get_digestbyname('sha1'), None)
328
329 def test_MessageDigest(self):
330 with self.assertRaises(ValueError):
331 @@ -66,6 +69,19 @@ class EVPTestCase(unittest.TestCase):
332 self.assertEqual(md.update('Hello'), 1)
333 self.assertEqual(util.octx_to_num(md.final()), 1415821221623963719413415453263690387336440359920)
334
335 + # temporarily remove sha1 from m2
336 + old_sha1 = m2.sha1
337 + del m2.sha1
338 +
339 + # now run the same test again, relying on EVP.MessageDigest() to call
340 + # get_digestbyname() under the hood
341 + md = EVP.MessageDigest('sha1')
342 + self.assertEqual(md.update('Hello'), 1)
343 + self.assertEqual(util.octx_to_num(md.final()), 1415821221623963719413415453263690387336440359920)
344 +
345 + # put sha1 back in place
346 + m2.sha1 = old_sha1
347 +
348 def test_as_der_capture_key(self):
349 """
350 Test DER encoding the PKey instance after assigning
351 @@ -140,6 +156,26 @@ class EVPTestCase(unittest.TestCase):
352 rsa3 = RSA.gen_key(1024, 3, callback=self._gen_callback)
353 self.assertNotEqual(rsa.sign(digest), rsa3.sign(digest))
354
355 + def test_load_key_string_pubkey(self):
356 + """
357 + Testing creating a PKey instance from PEM string.
358 + """
359 + rsa = RSA.gen_key(1024, 3, callback=self._gen_callback)
360 + self.assertIsInstance(rsa, RSA.RSA)
361 +
362 + rsa_pem = BIO.MemoryBuffer()
363 + rsa.save_pub_key_bio(rsa_pem)
364 + pkey = EVP.load_key_string_pubkey(rsa_pem.read())
365 + rsa2 = pkey.get_rsa()
366 + self.assertIsInstance(rsa2, RSA.RSA_pub)
367 + self.assertEqual(rsa.e, rsa2.e)
368 + self.assertEqual(rsa.n, rsa2.n)
369 + pem = rsa.as_pem(callback=self._pass_callback)
370 + pem2 = rsa2.as_pem()
371 + assert pem
372 + assert pem2
373 + self.assertNotEqual(pem, pem2)
374 +
375 def test_get_rsa_fail(self):
376 """
377 Testing trying to retrieve the RSA key from the PKey instance
0 diff -ur M2Crypto-0.22.3/M2Crypto/DSA.py M2Crypto-0.22.3.new/M2Crypto/DSA.py
1 --- M2Crypto-0.22.3/M2Crypto/DSA.py 2014-01-22 14:37:01.000000000 -0500
2 +++ M2Crypto-0.22.3.new/M2Crypto/DSA.py 2016-01-12 19:25:07.000000000 -0500
3 @@ -394,6 +394,29 @@
4 raise DSAError('problem loading DSA key pair')
5 return DSA(dsa, 1)
6
7 +def pub_key_from_params(p, q, g, pub):
8 + """
9 + Factory function that instantiates a DSA_pub object using
10 + the parameters and public key specified.
11 +
12 + @type p: str
13 + @param p: value of p, a "byte string"
14 + @type q: str
15 + @param q: value of q, a "byte string"
16 + @type g: str
17 + @param g: value of g, a "byte string"
18 + @type pub: str
19 + @param pub: value of the public key, a "byte string"
20 + @rtype: DSA_pub
21 + @return: instance of DSA_pub.
22 + """
23 + dsa = m2.dsa_new()
24 + m2.dsa_set_p(dsa, p)
25 + m2.dsa_set_q(dsa, q)
26 + m2.dsa_set_g(dsa, g)
27 + m2.dsa_set_pub(dsa, pub)
28 + return DSA_pub(dsa, 1)
29 +
30
31 def load_pub_key(file, callback=util.passphrase_callback):
32 """
33 diff -ur M2Crypto-0.22.3/M2Crypto/EC.py M2Crypto-0.22.3.new/M2Crypto/EC.py
34 --- M2Crypto-0.22.3/M2Crypto/EC.py 2014-01-22 14:37:01.000000000 -0500
35 +++ M2Crypto-0.22.3.new/M2Crypto/EC.py 2016-01-12 19:25:07.000000000 -0500
36 @@ -254,6 +254,13 @@
37 self.der = m2.ec_key_get_public_der(self.ec)
38 return self.der
39
40 + def get_key(self):
41 + """
42 + Returns the public key as a byte string.
43 + """
44 + assert self.check_key(), 'key is not initialised'
45 + return m2.ec_key_get_public_key(self.ec)
46 +
47 save_key = EC.save_pub_key
48
49 save_key_bio = EC.save_pub_key_bio
50 @@ -333,3 +340,9 @@
51 Create EC_pub from DER.
52 """
53 return EC_pub(m2.ec_key_from_pubkey_der(der), 1)
54 +
55 +def pub_key_from_params(curve, bytes):
56 + """
57 + Create EC_pub from curve name and octet string.
58 + """
59 + return EC_pub(m2.ec_key_from_pubkey_params(curve, bytes), 1)
60 diff -ur M2Crypto-0.22.3/M2Crypto/EVP.py M2Crypto-0.22.3.new/M2Crypto/EVP.py
61 --- M2Crypto-0.22.3/M2Crypto/EVP.py 2014-01-22 14:37:01.000000000 -0500
62 +++ M2Crypto-0.22.3.new/M2Crypto/EVP.py 2016-01-12 21:11:36.000000000 -0500
63 @@ -40,8 +40,13 @@
64 def __init__(self, algo):
65 md = getattr(m2, algo, None)
66 if md is None:
67 - raise ValueError, ('unknown algorithm', algo)
68 - self.md=md()
69 + # if the digest algorithm isn't found as an attribute of the m2
70 + # module, try to look up the digest using get_digestbyname()
71 + self.md = m2.get_digestbyname(algo)
72 + if self.md is None:
73 + raise ValueError('unknown algorithm', algo)
74 + else:
75 + self.md = md()
76 self.ctx=m2.md_ctx_new()
77 m2.digest_init(self.ctx, self.md)
78
79 @@ -389,6 +394,25 @@
80 raise EVPError(Err.get_error())
81 return PKey(cptr, 1)
82
83 +def load_key_bio_pubkey(bio, callback=util.passphrase_callback):
84 + """
85 + Load an M2Crypto.EVP.PKey from a public key as a M2Crypto.BIO object.
86 +
87 + @type bio: M2Crypto.BIO
88 + @param bio: M2Crypto.BIO object containing the key in PEM format.
89 +
90 + @type callback: Python callable
91 + @param callback: A Python callable object that is invoked
92 + to acquire a passphrase with which to protect the key.
93 +
94 + @rtype: M2Crypto.EVP.PKey
95 + @return: M2Crypto.EVP.PKey object.
96 + """
97 + cptr = m2.pkey_read_pem_pubkey(bio._ptr(), callback)
98 + if cptr is None:
99 + raise EVPError(Err.get_error())
100 + return PKey(cptr, 1)
101 +
102 def load_key_string(string, callback=util.passphrase_callback):
103 """
104 Load an M2Crypto.EVP.PKey from a string.
105 @@ -406,3 +430,19 @@
106 bio = BIO.MemoryBuffer(string)
107 return load_key_bio( bio, callback)
108
109 +def load_key_string_pubkey(string, callback=util.passphrase_callback):
110 + """
111 + Load an M2Crypto.EVP.PKey from a public key as a string.
112 +
113 + @type string: string
114 + @param string: String containing the key in PEM format.
115 +
116 + @type callback: Python callable
117 + @param callback: A Python callable object that is invoked
118 + to acquire a passphrase with which to protect the key.
119 +
120 + @rtype: M2Crypto.EVP.PKey
121 + @return: M2Crypto.EVP.PKey object.
122 + """
123 + bio = BIO.MemoryBuffer(string)
124 + return load_key_bio_pubkey(bio, callback)
125 diff -ur M2Crypto-0.22.3/SWIG/_dsa.i M2Crypto-0.22.3.new/SWIG/_dsa.i
126 --- M2Crypto-0.22.3/SWIG/_dsa.i 2014-01-22 14:37:01.000000000 -0500
127 +++ M2Crypto-0.22.3.new/SWIG/_dsa.i 2016-01-12 19:25:07.000000000 -0500
128 @@ -153,6 +153,25 @@
129 Py_INCREF(Py_None);
130 return Py_None;
131 }
132 +
133 +PyObject *dsa_set_pub(DSA *dsa, PyObject *value) {
134 + BIGNUM *bn;
135 + const void *vbuf;
136 + int vlen;
137 +
138 + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
139 + return NULL;
140 +
141 + if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) {
142 + PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error()));
143 + return NULL;
144 + }
145 + if (dsa->pub_key)
146 + BN_free(dsa->pub_key);
147 + dsa->pub_key = bn;
148 + Py_INCREF(Py_None);
149 + return Py_None;
150 +}
151 %}
152
153 %inline %{
154 diff -ur M2Crypto-0.22.3/SWIG/_ec.i M2Crypto-0.22.3.new/SWIG/_ec.i
155 --- M2Crypto-0.22.3/SWIG/_ec.i 2014-01-22 14:37:01.000000000 -0500
156 +++ M2Crypto-0.22.3.new/SWIG/_ec.i 2016-01-12 19:25:07.000000000 -0500
157 @@ -189,6 +189,43 @@
158
159 return pyo;
160 }
161 +
162 +PyObject *ec_key_get_public_key(EC_KEY *key) {
163 +
164 + unsigned char *src=NULL;
165 + void *dst=NULL;
166 + int src_len=0;
167 + Py_ssize_t dst_len=0;
168 + PyObject *pyo=NULL;
169 + int ret=0;
170 +
171 + /* Convert to binary */
172 + src_len = i2o_ECPublicKey(key, &src);
173 + if (src_len < 0)
174 + {
175 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
176 + return NULL;
177 + }
178 +
179 + /* Create a PyBuffer containing a copy of the binary,
180 + * to simplify memory deallocation
181 + */
182 + pyo = PyBuffer_New( src_len );
183 + ret = PyObject_AsWriteBuffer( pyo, &dst, &dst_len );
184 + assert( src_len == dst_len );
185 + if (ret < 0)
186 + {
187 + Py_DECREF(pyo);
188 + OPENSSL_free(src);
189 + PyErr_SetString(_ec_err, "cannot get write buffer");
190 + return NULL;
191 + }
192 + memcpy( dst, src, src_len );
193 + OPENSSL_free(src);
194 +
195 + return pyo;
196 +}
197 +
198 %}
199
200 %threadallow ec_key_read_pubkey;
201 @@ -404,6 +441,32 @@
202 return keypair;
203 }
204
205 +EC_KEY* ec_key_from_pubkey_params(int nid, PyObject *pubkey) {
206 + const void *keypairbuf;
207 + Py_ssize_t keypairbuflen;
208 + const unsigned char *tempBuf;
209 + EC_KEY *keypair;
210 +
211 + if (PyObject_AsReadBuffer(pubkey, &keypairbuf, &keypairbuflen) == -1)
212 + {
213 + return NULL;
214 + }
215 +
216 + keypair = ec_key_new_by_curve_name(nid);
217 + if (!keypair) {
218 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
219 + return NULL;
220 + }
221 +
222 + tempBuf = (const unsigned char *)keypairbuf;
223 + if ((o2i_ECPublicKey( &keypair, &tempBuf, keypairbuflen)) == 0)
224 + {
225 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
226 + return NULL;
227 + }
228 + return keypair;
229 +}
230 +
231
232 // According to [SEC2] the degree of the group is defined as EC key length
233 int ec_key_keylen(EC_KEY *key) {
234 diff -ur M2Crypto-0.22.3/SWIG/_evp.i M2Crypto-0.22.3.new/SWIG/_evp.i
235 --- M2Crypto-0.22.3/SWIG/_evp.i 2014-01-22 14:37:01.000000000 -0500
236 +++ M2Crypto-0.22.3.new/SWIG/_evp.i 2016-01-12 19:25:07.000000000 -0500
237 @@ -49,6 +49,9 @@
238 %rename(digest_init) EVP_DigestInit;
239 extern int EVP_DigestInit(EVP_MD_CTX *, const EVP_MD *);
240
241 +%rename(get_digestbyname) EVP_get_digestbyname;
242 +extern EVP_MD *EVP_get_digestbyname(const char * name);
243 +
244 %rename(des_ecb) EVP_des_ecb;
245 extern const EVP_CIPHER *EVP_des_ecb(void);
246 %rename(des_ede_ecb) EVP_des_ede;
247 @@ -506,6 +509,17 @@
248 return pk;
249 }
250
251 +EVP_PKEY *pkey_read_pem_pubkey(BIO *f, PyObject *pyfunc) {
252 + EVP_PKEY *pk;
253 +
254 + Py_INCREF(pyfunc);
255 + Py_BEGIN_ALLOW_THREADS
256 + pk = PEM_read_bio_PUBKEY(f, NULL, passphrase_callback, (void *)pyfunc);
257 + Py_END_ALLOW_THREADS
258 + Py_DECREF(pyfunc);
259 + return pk;
260 +}
261 +
262 int pkey_assign_rsa(EVP_PKEY *pkey, RSA *rsa) {
263 return EVP_PKEY_assign_RSA(pkey, rsa);
264 }
265 diff -ur M2Crypto-0.22.3/tests/test_dsa.py M2Crypto-0.22.3.new/tests/test_dsa.py
266 --- M2Crypto-0.22.3/tests/test_dsa.py 2014-01-22 14:37:01.000000000 -0500
267 +++ M2Crypto-0.22.3.new/tests/test_dsa.py 2016-01-12 19:25:07.000000000 -0500
268 @@ -87,6 +87,19 @@
269 r,s = dsa2.sign(self.data)
270 assert dsa2.verify(self.data, r, s)
271
272 + def test_pub_key_from_params(self):
273 + dsa = DSA.gen_params(1024, self.callback)
274 + dsa.gen_key()
275 + assert len(dsa) == 1024
276 + p = dsa.p
277 + q = dsa.q
278 + g = dsa.g
279 + pub = dsa.pub
280 + dsa2 = DSA.pub_key_from_params(p,q,g,pub)
281 + assert dsa2.check_key()
282 + r,s = dsa.sign(self.data)
283 + assert dsa2.verify(self.data, r, s)
284 +
285 def suite():
286 return unittest.makeSuite(DSATestCase)
287
288 diff -ur M2Crypto-0.22.3/tests/test_ecdsa.py M2Crypto-0.22.3.new/tests/test_ecdsa.py
289 --- M2Crypto-0.22.3/tests/test_ecdsa.py 2014-01-22 14:37:01.000000000 -0500
290 +++ M2Crypto-0.22.3.new/tests/test_ecdsa.py 2016-01-12 19:25:07.000000000 -0500
291 @@ -63,6 +63,16 @@
292 ec = EC.gen_params(EC.NID_sect233k1)
293 assert len(ec) == 233
294
295 + def test_pub_key_from_params(self):
296 + curve = EC.NID_X9_62_prime256v1
297 + ec = EC.gen_params(curve)
298 + ec.gen_key()
299 + ec_pub = ec.pub()
300 + k = ec_pub.get_key()
301 + ec2 = EC.pub_key_from_params(curve, k)
302 + assert ec2.check_key()
303 + r, s = ec.sign_dsa(self.data)
304 + assert ec2.verify_dsa(self.data, r, s)
305
306 def suite():
307 return unittest.makeSuite(ECDSATestCase)
308 diff -ur M2Crypto-0.22.3/tests/test_evp.py M2Crypto-0.22.3.new/tests/test_evp.py
309 --- M2Crypto-0.22.3/tests/test_evp.py 2014-01-22 14:37:01.000000000 -0500
310 +++ M2Crypto-0.22.3.new/tests/test_evp.py 2016-01-12 21:05:53.000000000 -0500
311 @@ -52,13 +52,25 @@
312 #A quick but not thorough sanity check
313 assert len(der_blob) == 160
314
315 -
316 def test_MessageDigest(self):
317 self.assertRaises(ValueError, EVP.MessageDigest, 'sha513')
318 md = EVP.MessageDigest('sha1')
319 assert md.update('Hello') == 1
320 assert util.octx_to_num(md.final()) == 1415821221623963719413415453263690387336440359920
321
322 + # temporarily remove sha1 from m2
323 + old_sha1 = m2.sha1
324 + del m2.sha1
325 +
326 + # now run the same test again, relying on EVP.MessageDigest() to call
327 + # get_digestbyname() under the hood
328 + md = EVP.MessageDigest('sha1')
329 + self.assertEqual(md.update('Hello'), 1)
330 + self.assertEqual(util.octx_to_num(md.final()), 1415821221623963719413415453263690387336440359920)
331 +
332 + # put sha1 back in place
333 + m2.sha1 = old_sha1
334 +
335 def test_as_der_capture_key(self):
336 """
337 Test DER encoding the PKey instance after assigning
338 @@ -92,6 +104,9 @@
339
340 self.assertRaises(ValueError, EVP.hmac, 'key', 'data', algo='sha513')
341
342 + def test_get_digestbyname(self):
343 + self.assertEqual(m2.get_digestbyname('sha513'), None)
344 + self.assertNotEqual(m2.get_digestbyname('sha1'), None)
345
346 def test_get_rsa(self):
347 """
348 @@ -117,7 +132,27 @@
349
350 rsa3 = RSA.gen_key(1024, 3, callback=self._gen_callback)
351 assert rsa.sign(digest) != rsa3.sign(digest)
352 -
353 +
354 + def test_load_key_string_pubkey(self):
355 + """
356 + Testing creating a PKey instance from PEM string.
357 + """
358 + rsa = RSA.gen_key(1024, 3, callback=self._gen_callback)
359 + self.assertIsInstance(rsa, RSA.RSA)
360 +
361 + rsa_pem = BIO.MemoryBuffer()
362 + rsa.save_pub_key_bio(rsa_pem)
363 + pkey = EVP.load_key_string_pubkey(rsa_pem.read())
364 + rsa2 = pkey.get_rsa()
365 + self.assertIsInstance(rsa2, RSA.RSA_pub)
366 + self.assertEqual(rsa.e, rsa2.e)
367 + self.assertEqual(rsa.n, rsa2.n)
368 + pem = rsa.as_pem(callback=self._pass_callback)
369 + pem2 = rsa2.as_pem()
370 + assert pem
371 + assert pem2
372 + self.assertNotEqual(pem, pem2)
373 +
374 def test_get_rsa_fail(self):
375 """
376 Testing trying to retrieve the RSA key from the PKey instance
+0
-229
contrib/m2crypto.patch less more
0 diff -uar m2crypto-0.21.1/M2Crypto/DSA.py m2crypto-0.21.1.new/M2Crypto/DSA.py
1 --- m2crypto-0.21.1/M2Crypto/DSA.py 2011-01-15 11:10:05.000000000 -0800
2 +++ m2crypto-0.21.1.new/M2Crypto/DSA.py 2013-05-16 13:32:43.100275223 -0700
3 @@ -394,6 +394,29 @@
4 raise DSAError('problem loading DSA key pair')
5 return DSA(dsa, 1)
6
7 +def pub_key_from_params(p, q, g, pub):
8 + """
9 + Factory function that instantiates a DSA_pub object using
10 + the parameters and public key specified.
11 +
12 + @type p: str
13 + @param p: value of p, a "byte string"
14 + @type q: str
15 + @param q: value of q, a "byte string"
16 + @type g: str
17 + @param g: value of g, a "byte string"
18 + @type pub: str
19 + @param pub: value of the public key, a "byte string"
20 + @rtype: DSA_pub
21 + @return: instance of DSA_pub.
22 + """
23 + dsa = m2.dsa_new()
24 + m2.dsa_set_p(dsa, p)
25 + m2.dsa_set_q(dsa, q)
26 + m2.dsa_set_g(dsa, g)
27 + m2.dsa_set_pub(dsa, pub)
28 + return DSA_pub(dsa, 1)
29 +
30
31 def load_pub_key(file, callback=util.passphrase_callback):
32 """
33 diff -uar m2crypto-0.21.1/M2Crypto/EC.py m2crypto-0.21.1.new/M2Crypto/EC.py
34 --- m2crypto-0.21.1/M2Crypto/EC.py 2011-01-15 11:10:05.000000000 -0800
35 +++ m2crypto-0.21.1.new/M2Crypto/EC.py 2013-05-16 13:32:43.100275223 -0700
36 @@ -333,3 +333,9 @@
37 Create EC_pub from DER.
38 """
39 return EC_pub(m2.ec_key_from_pubkey_der(der), 1)
40 +
41 +def pub_key_from_params(curve, bytes):
42 + """
43 + Create EC_pub from curve name and octet string.
44 + """
45 + return EC_pub(m2.ec_key_from_pubkey_params(curve, bytes), 1)
46 diff -uar m2crypto-0.21.1/M2Crypto/EVP.py m2crypto-0.21.1.new/M2Crypto/EVP.py
47 --- m2crypto-0.21.1/M2Crypto/EVP.py 2011-01-15 11:10:05.000000000 -0800
48 +++ m2crypto-0.21.1.new/M2Crypto/EVP.py 2013-05-16 13:32:43.100275223 -0700
49 @@ -389,6 +389,25 @@
50 raise EVPError(Err.get_error())
51 return PKey(cptr, 1)
52
53 +def load_key_bio_pubkey(bio, callback=util.passphrase_callback):
54 + """
55 + Load an M2Crypto.EVP.PKey from a public key as a M2Crypto.BIO object.
56 +
57 + @type bio: M2Crypto.BIO
58 + @param bio: M2Crypto.BIO object containing the key in PEM format.
59 +
60 + @type callback: Python callable
61 + @param callback: A Python callable object that is invoked
62 + to acquire a passphrase with which to protect the key.
63 +
64 + @rtype: M2Crypto.EVP.PKey
65 + @return: M2Crypto.EVP.PKey object.
66 + """
67 + cptr = m2.pkey_read_pem_pubkey(bio._ptr(), callback)
68 + if cptr is None:
69 + raise EVPError(Err.get_error())
70 + return PKey(cptr, 1)
71 +
72 def load_key_string(string, callback=util.passphrase_callback):
73 """
74 Load an M2Crypto.EVP.PKey from a string.
75 @@ -406,3 +425,20 @@
76 bio = BIO.MemoryBuffer(string)
77 return load_key_bio( bio, callback)
78
79 +def load_key_string_pubkey(string, callback=util.passphrase_callback):
80 + """
81 + Load an M2Crypto.EVP.PKey from a public key as a string.
82 +
83 + @type string: string
84 + @param string: String containing the key in PEM format.
85 +
86 + @type callback: Python callable
87 + @param callback: A Python callable object that is invoked
88 + to acquire a passphrase with which to protect the key.
89 +
90 + @rtype: M2Crypto.EVP.PKey
91 + @return: M2Crypto.EVP.PKey object.
92 + """
93 + bio = BIO.MemoryBuffer(string)
94 + return load_key_bio_pubkey( bio, callback)
95 +
96 diff -uar m2crypto-0.21.1/SWIG/_dsa.i m2crypto-0.21.1.new/SWIG/_dsa.i
97 --- m2crypto-0.21.1/SWIG/_dsa.i 2011-01-15 11:10:06.000000000 -0800
98 +++ m2crypto-0.21.1.new/SWIG/_dsa.i 2013-05-16 13:32:43.100275223 -0700
99 @@ -153,6 +153,25 @@
100 Py_INCREF(Py_None);
101 return Py_None;
102 }
103 +
104 +PyObject *dsa_set_pub(DSA *dsa, PyObject *value) {
105 + BIGNUM *bn;
106 + const void *vbuf;
107 + int vlen;
108 +
109 + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
110 + return NULL;
111 +
112 + if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) {
113 + PyErr_SetString(_dsa_err, ERR_reason_error_string(ERR_get_error()));
114 + return NULL;
115 + }
116 + if (dsa->pub_key)
117 + BN_free(dsa->pub_key);
118 + dsa->pub_key = bn;
119 + Py_INCREF(Py_None);
120 + return Py_None;
121 +}
122 %}
123
124 %inline %{
125 diff -uar m2crypto-0.21.1/SWIG/_ec.i m2crypto-0.21.1.new/SWIG/_ec.i
126 --- m2crypto-0.21.1/SWIG/_ec.i 2011-01-15 11:10:06.000000000 -0800
127 +++ m2crypto-0.21.1.new/SWIG/_ec.i 2013-05-16 13:32:43.100275223 -0700
128 @@ -404,6 +404,46 @@
129 return keypair;
130 }
131
132 +EC_KEY* ec_key_from_pubkey_params(int nid, PyObject *pubkey) {
133 + const void *pubkeybuf;
134 + Py_ssize_t pubkeybuflen;
135 + const unsigned char *tempBuf;
136 + unsigned char *buf;
137 + EC_KEY *eckey;
138 + EC_KEY *neweckey;
139 +
140 + if (PyObject_AsReadBuffer(pubkey, &pubkeybuf, &pubkeybuflen) == -1)
141 + {
142 + return NULL;
143 + }
144 +
145 + eckey = EC_KEY_new_by_curve_name(nid);
146 + if (!eckey) {
147 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
148 + return NULL;
149 + }
150 +
151 + buf = (unsigned char*)OPENSSL_malloc(pubkeybuflen+1);
152 + if (!buf) {
153 + PyErr_SetString(PyExc_MemoryError, "ec_key_from_pubkey_bytes");
154 + return NULL;
155 + }
156 + buf[0] = POINT_CONVERSION_UNCOMPRESSED;
157 + memcpy(buf + 1, pubkeybuf, pubkeybuflen);
158 +
159 + tempBuf = (const unsigned char *)buf;
160 + if ((neweckey = o2i_ECPublicKey( &eckey, &tempBuf, pubkeybuflen+1)) == 0)
161 + {
162 + OPENSSL_cleanse(buf, pubkeybuflen+1);
163 + OPENSSL_free(buf);
164 + PyErr_SetString(_ec_err, ERR_reason_error_string(ERR_get_error()));
165 + return NULL;
166 + }
167 + OPENSSL_cleanse(buf, pubkeybuflen+1);
168 + OPENSSL_free(buf);
169 + return neweckey;
170 +}
171 +
172
173 // According to [SEC2] the degree of the group is defined as EC key length
174 int ec_key_keylen(EC_KEY *key) {
175 diff -uar m2crypto-0.21.1/SWIG/_evp.i m2crypto-0.21.1.new/SWIG/_evp.i
176 --- m2crypto-0.21.1/SWIG/_evp.i 2011-01-15 11:10:06.000000000 -0800
177 +++ m2crypto-0.21.1.new/SWIG/_evp.i 2013-05-16 13:32:43.104275275 -0700
178 @@ -49,6 +49,9 @@
179 %rename(digest_init) EVP_DigestInit;
180 extern int EVP_DigestInit(EVP_MD_CTX *, const EVP_MD *);
181
182 +%rename(get_digestbyname) EVP_get_digestbyname;
183 +extern EVP_MD *EVP_get_digestbyname(const char * name);
184 +
185 %rename(des_ecb) EVP_des_ecb;
186 extern const EVP_CIPHER *EVP_des_ecb(void);
187 %rename(des_ede_ecb) EVP_des_ede;
188 @@ -504,6 +507,17 @@
189 Py_END_ALLOW_THREADS
190 Py_DECREF(pyfunc);
191 return pk;
192 +}
193 +
194 +EVP_PKEY *pkey_read_pem_pubkey(BIO *f, PyObject *pyfunc) {
195 + EVP_PKEY *pk;
196 +
197 + Py_INCREF(pyfunc);
198 + Py_BEGIN_ALLOW_THREADS
199 + pk = PEM_read_bio_PUBKEY(f, NULL, passphrase_callback, (void *)pyfunc);
200 + Py_END_ALLOW_THREADS
201 + Py_DECREF(pyfunc);
202 + return pk;
203 }
204
205 int pkey_assign_rsa(EVP_PKEY *pkey, RSA *rsa) {
206 diff -uar m2crypto-0.21.1/tests/test_dsa.py m2crypto-0.21.1.new/tests/test_dsa.py
207 --- m2crypto-0.21.1/tests/test_dsa.py 2011-01-15 11:10:05.000000000 -0800
208 +++ m2crypto-0.21.1.new/tests/test_dsa.py 2013-05-16 13:32:43.104275275 -0700
209 @@ -87,6 +87,19 @@
210 r,s = dsa2.sign(self.data)
211 assert dsa2.verify(self.data, r, s)
212
213 + def test_pub_key_from_params(self):
214 + dsa = DSA.gen_params(1024, self.callback)
215 + dsa.gen_key()
216 + assert len(dsa) == 1024
217 + p = dsa.p
218 + q = dsa.q
219 + g = dsa.g
220 + pub = dsa.pub
221 + dsa2 = DSA.pub_key_from_params(p,q,g,pub)
222 + assert dsa2.check_key()
223 + r,s = dsa.sign(self.data)
224 + assert dsa2.verify(self.data, r, s)
225 +
226 def suite():
227 return unittest.makeSuite(DSATestCase)
228
2424 JQUERY_UI_PATH = __JQUERY_UI_PATH__
2525 JQUERY_UI_CSS_PATH = __JQUERY_UI_CSS_PATH__
2626 RAPHAEL_PATH = __RAPHAEL_PATH__
27 GOST_PATH = __GOST_PATH__
2727 import base64
2828 import struct
2929 import hashlib
30
31 from dnsviz.config import GOST_PATH
3032
3133 try:
3234 from M2Crypto import EVP, RSA
4345 GOST_PREFIX = '\x30\x63\x30\x1c\x06\x06\x2a\x85\x03\x02\x02\x13\x30\x12\x06\x07\x2a\x85\x03\x02\x02\x23\x01\x06\x07\x2a\x85\x03\x02\x02\x1e\x01\x03\x43\x00\x04\x40'
4446 GOST_DIGEST_NAME = 'GOST R 34.11-94'
4547
48 EC_NOCOMPRESSION = '\x04'
49
4650 def _check_dsa_support():
4751 try:
4852 DSA.pub_key_from_params
5155 pass
5256
5357 def _check_gost_support():
54 try:
55 _gost_init()
58 if GOST_PATH is not None:
5659 try:
57 m2.get_digestbyname(GOST_DIGEST_NAME)
58 except AttributeError:
60 _gost_init()
61 try:
62 md = EVP.MessageDigest(GOST_DIGEST_NAME)
63 except ValueError:
64 pass
65 else:
66 _supported_algs.add(12)
67 _supported_digest_algs.add(3)
68 _gost_cleanup()
69 except Engine.EngineError:
5970 pass
60 else:
61 _supported_algs.add(12)
62 _supported_digest_algs.add(3)
63 _gost_cleanup()
64 except Engine.EngineError:
65 pass
6671
6772 def _check_ec_support():
6873 try:
8186 return alg in _supported_nsec3_algs
8287
8388 def _gost_init():
84 gost = Engine.load_dynamic_engine('gost', '/usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines/libgost.so')
89 gost = Engine.load_dynamic_engine('gost', GOST_PATH)
8590 gost.init()
8691 gost.set_default()
8792
104109 pass
105110 else:
106111 _check_gost_support()
107
108 class GostMessageDigest(EVP.MessageDigest):
109 def __init__(self, md):
110 self.md=md
111 self.ctx=m2.md_ctx_new()
112 m2.digest_init(self.ctx, self.md)
113112
114113 try:
115114 from M2Crypto import EC
133132 elif digest_alg == 3:
134133 _gost_init()
135134 try:
136 mdgost = m2.get_digestbyname(GOST_DIGEST_NAME)
137 md = GostMessageDigest(mdgost)
135 md = EVP.MessageDigest(GOST_DIGEST_NAME)
138136 md.update(dnskey_msg)
139137 return md.final() == digest
140138 finally:
230228 else:
231229 raise ValueError('Algorithm not supported')
232230
233 return EC.pub_key_from_params(curve, key)
231 return EC.pub_key_from_params(curve, EC_NOCOMPRESSION + key)
234232
235233 def _validate_rrsig_rsa(alg, sig, msg, key):
236234 pubkey = _dnskey_to_rsa(key)
1313 JQUERY_UI_CSS_PATH = "'http://code.jquery.com/ui/1.11.4/themes/redmond/jquery-ui.css'"
1414 JQUERY_PATH = "'http://code.jquery.com/jquery-1.11.3.min.js'"
1515 RAPHAEL_PATH = "'http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.4/raphael-min.js'"
16 GOST_PATH = "'/usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines/libgost.so'"
1617
1718 def apply_substitutions(filename, install_prefix):
1819 assert filename.endswith('.in'), 'Filename supplied for customization must end with \'.in\': %s' % (filename)
3031 s = s.replace('__JQUERY_UI_PATH__', JQUERY_UI_PATH)
3132 s = s.replace('__JQUERY_UI_CSS_PATH__', JQUERY_UI_CSS_PATH)
3233 s = s.replace('__RAPHAEL_PATH__', RAPHAEL_PATH)
34 s = s.replace('__GOST_PATH__', GOST_PATH)
3335 out_fh.write(s)
3436 in_fh.close()
3537 out_fh.close()