File Coverage

SEC.xs
Criterion Covered Total %
statement 77 77 100.0
branch 6 6 100.0
condition n/a
subroutine n/a
pod n/a
total 83 83 100.0


line stmt bran cond sub pod time code
1              
2             #define XS_Id "$Id: SEC.xs 1926 2023-05-31 12:05:13Z willem $"
3              
4              
5             =head1 NAME
6              
7             Net::DNS::SEC::libcrypto - Perl interface to OpenSSL libcrypto
8              
9             =head1 DESCRIPTION
10              
11             Perl XS extension providing access to the OpenSSL libcrypto library
12             upon which the Net::DNS::SEC cryptographic components are built.
13              
14             =head1 COPYRIGHT
15              
16             Copyright (c)2018-2021 Dick Franks
17              
18             All Rights Reserved
19              
20             =head1 LICENSE
21              
22             Permission to use, copy, modify, and distribute this software and its
23             documentation for any purpose and without fee is hereby granted, provided
24             that the original copyright notices appear in all copies and that both
25             copyright notice and this permission notice appear in supporting
26             documentation, and that the name of the author not be used in advertising
27             or publicity pertaining to distribution of the software without specific
28             prior written permission.
29              
30             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33             THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35             FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36             DEALINGS IN THE SOFTWARE.
37              
38             =cut
39              
40              
41             #ifdef __cplusplus
42             extern "C" {
43             #endif
44              
45             #define PERL_NO_GET_CONTEXT
46             #define PERL_REENTRANT
47             #include
48             #include
49             #include
50              
51             #include
52             #include
53             #include
54              
55             #ifndef OPENSSL_VERSION_NUMBER /* 0xMNN00PP0L retain backward compatibility */
56             #define OPENSSL_VERSION_NUMBER \
57             ( (OPENSSL_VERSION_MAJOR<<28) | (OPENSSL_VERSION_MINOR<<20) | (OPENSSL_VERSION_PATCH<<4) | 0x0L )
58             #endif
59              
60             #if (OPENSSL_VERSION_NUMBER < 0x40000000)
61             #define OBSOLETE_API
62             #undef OSSL_DEPRECATED
63             #define OSSL_DEPRECATED(since) extern
64             #include
65             #include
66             #include
67             #include
68             #include
69             #else
70             #include
71             #include
72             #include
73             static OSSL_LIB_CTX *libctx = NULL;
74             #endif
75              
76             #ifdef __cplusplus
77             }
78             #endif
79              
80              
81             #ifdef OPENSSL_NO_DSA
82             #define NO_DSA
83             #endif
84              
85             #ifdef OPENSSL_NO_RSA
86             #define NO_RSA
87             #endif
88              
89             #ifdef OPENSSL_NO_EC
90             #define NO_ECDSA
91             #define NO_EdDSA
92             #endif
93              
94             #ifdef OPENSSL_IS_BORINGSSL
95             #define NO_DSA
96             #define NO_EdDSA
97             #define NO_SHA3
98             #endif
99              
100             #ifdef LIBRESSL_VERSION_NUMBER
101             #undef OPENSSL_VERSION_NUMBER
102             #define OPENSSL_VERSION_NUMBER 0x10100000L
103             #endif
104              
105              
106             #if (OPENSSL_VERSION_NUMBER < 0x10001000)
107             #error unsupported libcrypto version
108             #include OPENSSL_VERSION_TEXT /* in error log; by any means, however reprehensible! */
109             #endif
110              
111              
112             #if (OPENSSL_VERSION_NUMBER < 0x10100000)
113              
114             #define EVP_MD_CTX_new() EVP_MD_CTX_create()
115             #define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy((ctx))
116              
117 3           int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
118             {
119 3           d->p = p;
120 3           d->q = q;
121 3           d->g = g;
122 3           return 1;
123             }
124              
125 3           int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
126             {
127 3           d->priv_key = priv_key;
128 3           d->pub_key = pub_key;
129 3           return 1;
130             }
131              
132 43           int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
133             {
134 43           r->n = n;
135 43           r->e = e;
136 43           r->d = d;
137 43           return 1;
138             }
139              
140 43           int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
141             {
142 43           r->p = p;
143 43           r->q = q;
144 43           return 1;
145             }
146             #endif
147              
148              
149             #if (OPENSSL_VERSION_NUMBER < 0x10101000)
150             #define EOL
151             #define NO_EdDSA
152             #define NO_SHA3
153              
154 14           int EVP_DigestSign(EVP_MD_CTX *ctx,
155             unsigned char *sig, size_t *sig_len,
156             const unsigned char *data, size_t data_len)
157             {
158 14           EVP_DigestUpdate( ctx, data, data_len );
159 14           return EVP_DigestSignFinal( ctx, sig, sig_len );
160             }
161              
162 38           int EVP_DigestVerify(EVP_MD_CTX *ctx,
163             const unsigned char *sig, size_t sig_len,
164             const unsigned char *data, size_t data_len)
165             {
166 38           EVP_DigestUpdate( ctx, data, data_len );
167 38           return EVP_DigestVerifyFinal( ctx, sig, sig_len );
168             }
169             #endif
170              
171              
172             #ifndef OBSOLETE_API
173             int EVP_PKEY_fromparams(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection, OSSL_PARAM_BLD *bld)
174             {
175             OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);
176             int retval = EVP_PKEY_fromdata_init(ctx);
177             if ( retval > 0 ) retval = EVP_PKEY_fromdata( ctx, ppkey, selection, params );
178             OSSL_PARAM_free(params);
179             return retval;
180             }
181             #endif
182              
183              
184             #define checkerr(arg) checkret( (arg), __LINE__ )
185 265           void checkret(const int ret, int line)
186             {
187 265 100         if ( ret <= 0 ) croak( "libcrypto error (%s line %d)", __FILE__, line );
188 264           }
189              
190              
191             MODULE = Net::DNS::SEC PACKAGE = Net::DNS::SEC::libcrypto
192              
193             PROTOTYPES: ENABLE
194              
195             SV*
196             VERSION(void)
197             PREINIT:
198 2           char *v = SvEND( newSVpv(XS_Id, 17) );
199             CODE:
200             #ifdef EOL
201 2           RETVAL = newSVpvf( "%s %s [UNSUPPORTED]", v-5, OPENSSL_VERSION_TEXT );
202             #else
203             RETVAL = newSVpvf( "%s %s", v-5, OPENSSL_VERSION_TEXT );
204             #endif
205             OUTPUT:
206             RETVAL
207              
208              
209             #### EVP ####
210              
211             EVP_PKEY*
212             EVP_PKEY_new()
213              
214             SV*
215             EVP_sign(SV *message, EVP_PKEY *pkey, const EVP_MD *md=NULL)
216             INIT:
217             #define msgbuf (unsigned char*) SvPVX(message)
218             #define msglen SvCUR(message)
219 14           EVP_MD_CTX *ctx = EVP_MD_CTX_new();
220             unsigned char sigbuf[512]; /* RFC3110(2) */
221 14           STRLEN buflen = sizeof(sigbuf);
222             int error;
223             CODE:
224 14           checkerr( EVP_DigestSignInit( ctx, NULL, md, NULL, pkey ) );
225 14           error = EVP_DigestSign( ctx, sigbuf, &buflen, msgbuf, msglen );
226 14           EVP_MD_CTX_free(ctx);
227 14           EVP_PKEY_free(pkey);
228 14           checkerr(error);
229 14           RETVAL = newSVpvn( (char*)sigbuf, buflen );
230             OUTPUT:
231             RETVAL
232              
233             int
234             EVP_verify(SV *message, SV *signature, EVP_PKEY *pkey, const EVP_MD *md=NULL)
235             INIT:
236             #define sigbuf (unsigned char*) SvPVX(signature)
237             #define siglen SvCUR(signature)
238 38           EVP_MD_CTX *ctx = EVP_MD_CTX_new();
239             CODE:
240 38           checkerr( EVP_DigestVerifyInit( ctx, NULL, md, NULL, pkey ) );
241 38           RETVAL = EVP_DigestVerify( ctx, sigbuf, siglen, msgbuf, msglen );
242 38           EVP_MD_CTX_free(ctx);
243 38           EVP_PKEY_free(pkey);
244             OUTPUT:
245             RETVAL
246              
247              
248             EVP_MD_CTX*
249             EVP_MD_CTX_new()
250              
251             void
252             EVP_MD_CTX_free(EVP_MD_CTX *ctx)
253              
254             void
255             EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
256             CODE:
257 18           checkerr( EVP_DigestInit( ctx, type ) );
258              
259             void
260             EVP_DigestUpdate(EVP_MD_CTX *ctx, SV *message)
261             CODE:
262 18           checkerr( EVP_DigestUpdate( ctx, msgbuf, msglen ) );
263              
264             SV*
265             EVP_DigestFinal(EVP_MD_CTX *ctx)
266             INIT:
267             unsigned char digest[EVP_MAX_MD_SIZE];
268 12           unsigned int size = sizeof(digest);
269             CODE:
270 12           checkerr( EVP_DigestFinal( ctx, digest, &size ) );
271 12           RETVAL = newSVpvn( (char*)digest, size );
272             OUTPUT:
273             RETVAL
274              
275              
276             const EVP_MD*
277             EVP_md5()
278              
279             const EVP_MD*
280             EVP_sha1()
281              
282             const EVP_MD*
283             EVP_sha224()
284              
285             const EVP_MD*
286             EVP_sha256()
287              
288             const EVP_MD*
289             EVP_sha384()
290              
291             const EVP_MD*
292             EVP_sha512()
293              
294              
295             #ifndef NO_SHA3
296             const EVP_MD*
297             EVP_sha3_224()
298              
299             const EVP_MD*
300             EVP_sha3_256()
301              
302             const EVP_MD*
303             EVP_sha3_384()
304              
305             const EVP_MD*
306             EVP_sha3_512()
307              
308             #endif
309              
310              
311             #### DSA ####
312              
313             #ifndef NO_DSA
314              
315             EVP_PKEY*
316             EVP_PKEY_new_DSA(SV *p_SV, SV *q_SV, SV *g_SV, SV *y_SV, SV *x_SV)
317             INIT:
318 3           BIGNUM *p = BN_bin2bn( (unsigned char*) SvPVX(p_SV), SvCUR(p_SV), NULL );
319 3           BIGNUM *q = BN_bin2bn( (unsigned char*) SvPVX(q_SV), SvCUR(q_SV), NULL );
320 3           BIGNUM *g = BN_bin2bn( (unsigned char*) SvPVX(g_SV), SvCUR(g_SV), NULL );
321 3 100         BIGNUM *x = SvCUR(x_SV) == 0 ? NULL : BN_bin2bn( (unsigned char*) SvPVX(x_SV), SvCUR(x_SV), NULL );
322 3           BIGNUM *y = BN_bin2bn( (unsigned char*) SvPVX(y_SV), SvCUR(y_SV), NULL );
323             CODE:
324             #ifdef OBSOLETE_API
325 3           DSA *dsa = DSA_new();
326 3           checkerr( DSA_set0_pqg( dsa, p, q, g ) );
327 3           checkerr( DSA_set0_key( dsa, y, x ) );
328 3           RETVAL = EVP_PKEY_new();
329 3           checkerr( EVP_PKEY_assign( RETVAL, EVP_PKEY_DSA, (char*)dsa ) );
330             #else
331             EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name( libctx, "DSA", NULL );
332             OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
333             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_FFC_P, p ) );
334             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_FFC_Q, q ) );
335             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_FFC_G, g ) );
336             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_PUB_KEY, y ) );
337             RETVAL = NULL;
338             if ( SvCUR(x_SV) > 0 ) {
339             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_PRIV_KEY, x ) );
340             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_KEYPAIR, bld ) );
341             } else {
342             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_PUBLIC_KEY, bld ) );
343             }
344             OSSL_PARAM_BLD_free(bld);
345             EVP_PKEY_CTX_free(ctx);
346             BN_free(p);
347             BN_free(q);
348             BN_free(g);
349             BN_free(x);
350             BN_free(y);
351             #endif
352             OUTPUT:
353             RETVAL
354              
355             #endif
356              
357              
358             #### RSA ####
359              
360             #ifndef NO_RSA
361              
362             EVP_PKEY*
363             EVP_PKEY_new_RSA(SV *n_SV, SV *e_SV, SV *d_SV, SV *p_SV, SV *q_SV)
364             INIT:
365 43           BIGNUM *n = BN_bin2bn( (unsigned char*) SvPVX(n_SV), SvCUR(n_SV), NULL );
366 43           BIGNUM *e = BN_bin2bn( (unsigned char*) SvPVX(e_SV), SvCUR(e_SV), NULL );
367 43           BIGNUM *d = BN_bin2bn( (unsigned char*) SvPVX(d_SV), SvCUR(d_SV), NULL );
368 43           BIGNUM *p = BN_bin2bn( (unsigned char*) SvPVX(p_SV), SvCUR(p_SV), NULL );
369 43           BIGNUM *q = BN_bin2bn( (unsigned char*) SvPVX(q_SV), SvCUR(q_SV), NULL );
370             CODE:
371             #ifdef OBSOLETE_API
372 43           RSA *rsa = RSA_new();
373 43           checkerr( RSA_set0_factors( rsa, p, q ) );
374 43           checkerr( RSA_set0_key( rsa, n, e, d ) );
375 43           RETVAL = EVP_PKEY_new();
376 43           checkerr( EVP_PKEY_assign( RETVAL, EVP_PKEY_RSA, (char*)rsa ) );
377             #else
378             EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name( libctx, "RSA", NULL );
379             OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
380             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_RSA_N, n ) );
381             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_RSA_E, e ) );
382             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_RSA_D, d ) );
383             RETVAL = NULL;
384             if ( SvCUR(p_SV) > 0 ) {
385             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_RSA_FACTOR, p ) );
386             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_RSA_FACTOR, q ) );
387             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_KEYPAIR, bld ) );
388             } else {
389             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_PUBLIC_KEY, bld ) );
390             }
391             OSSL_PARAM_BLD_free(bld);
392             EVP_PKEY_CTX_free(ctx);
393             BN_free(n);
394             BN_free(e);
395             BN_free(d);
396             BN_free(p);
397             BN_free(q);
398             #endif
399             OUTPUT:
400             RETVAL
401              
402             #endif
403              
404              
405             #### ECDSA ####
406              
407             #ifndef NO_ECDSA
408              
409             EVP_PKEY*
410             EVP_PKEY_new_ECDSA(int nid, SV *qx_SV, SV *qy_SV)
411             INIT:
412 6           BIGNUM *qx = BN_bin2bn( (unsigned char*) SvPVX(qx_SV), SvCUR(qx_SV), NULL );
413 6           BIGNUM *qy = BN_bin2bn( (unsigned char*) SvPVX(qy_SV), SvCUR(qy_SV), NULL );
414             #ifdef OBSOLETE_API
415 6           EC_KEY *eckey = EC_KEY_new_by_curve_name(nid);
416             #else
417             EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name( libctx, "EC", NULL );
418             OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
419             #endif
420             CODE:
421             #ifdef OBSOLETE_API
422 6 100         if ( SvCUR(qy_SV) > 0 ) {
423 4           checkerr( EC_KEY_set_public_key_affine_coordinates( eckey, qx, qy ) );
424             } else {
425 2           checkerr( EC_KEY_set_private_key( eckey, qx ) );
426             }
427 6           RETVAL = EVP_PKEY_new();
428 6           checkerr( EVP_PKEY_assign( RETVAL, EVP_PKEY_EC, (char*)eckey ) );
429             #else
430             if ( nid == 415 ) checkerr( OSSL_PARAM_BLD_push_utf8_string( bld, OSSL_PKEY_PARAM_GROUP_NAME, "P-256", 0 ) );
431             if ( nid == 715 ) checkerr( OSSL_PARAM_BLD_push_utf8_string( bld, OSSL_PKEY_PARAM_GROUP_NAME, "P-384", 0 ) );
432             RETVAL = NULL;
433             if ( SvCUR(qy_SV) > 0 ) {
434             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_EC_PUB_X, qx ) );
435             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_EC_PUB_Y, qy ) );
436             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_PUBLIC_KEY, bld ) );
437             } else {
438             checkerr( OSSL_PARAM_BLD_push_BN( bld, OSSL_PKEY_PARAM_PRIV_KEY, qx ) );
439             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_KEYPAIR, bld ) );
440             }
441             OSSL_PARAM_BLD_free(bld);
442             EVP_PKEY_CTX_free(ctx);
443             #endif
444 6           BN_clear_free(qx);
445 6           BN_clear_free(qy);
446             OUTPUT:
447             RETVAL
448              
449             #endif
450              
451              
452             #### EdDSA ####
453              
454             #ifndef NO_EdDSA
455              
456             EVP_PKEY*
457             EVP_PKEY_new_raw_public_key(int nid, SV *key)
458             CODE:
459             #define rawkey (unsigned char*) SvPVX(key)
460             #define keylen SvCUR(key)
461             #ifdef OBSOLETE_API
462             RETVAL = EVP_PKEY_new_raw_public_key( nid, NULL, rawkey , keylen );
463             #else
464             EVP_PKEY_CTX *ctx = NULL;
465             OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
466             RETVAL = NULL;
467             if ( nid == 1087 ) ctx = EVP_PKEY_CTX_new_from_name( libctx, "ED25519", NULL );
468             if ( nid == 1088 ) ctx = EVP_PKEY_CTX_new_from_name( libctx, "ED448", NULL );
469             checkerr( OSSL_PARAM_BLD_push_octet_string( bld, OSSL_PKEY_PARAM_PUB_KEY, rawkey, keylen ) );
470             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_PUBLIC_KEY, bld ) );
471             OSSL_PARAM_BLD_free(bld);
472             EVP_PKEY_CTX_free(ctx);
473             #endif
474             OUTPUT:
475             RETVAL
476              
477             EVP_PKEY*
478             EVP_PKEY_new_raw_private_key(int nid, SV *key)
479             CODE:
480             #ifdef OBSOLETE_API
481             RETVAL = EVP_PKEY_new_raw_private_key( nid, NULL, rawkey , keylen );
482             #else
483             EVP_PKEY_CTX *ctx = NULL;
484             OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
485             RETVAL = NULL;
486             if ( nid == 1087 ) ctx = EVP_PKEY_CTX_new_from_name( libctx, "ED25519", NULL );
487             if ( nid == 1088 ) ctx = EVP_PKEY_CTX_new_from_name( libctx, "ED448", NULL );
488             checkerr( OSSL_PARAM_BLD_push_octet_string( bld, OSSL_PKEY_PARAM_PRIV_KEY, rawkey, keylen ) );
489             checkerr( EVP_PKEY_fromparams( ctx, &RETVAL, EVP_PKEY_KEYPAIR, bld ) );
490             OSSL_PARAM_BLD_free(bld);
491             EVP_PKEY_CTX_free(ctx);
492             #endif
493             OUTPUT:
494             RETVAL
495              
496             #endif
497              
498              
499             ####################
500              
501             void
502             checkerr(int ret)
503              
504              
505             #ifdef croak_memory_wrap
506             void
507             croak_memory_wrap()
508              
509             #endif
510              
511              
512             #ifdef DEBUG
513             void
514             ERR_print_errors(SV *filename)
515             CODE:
516             BIO *bio = BIO_new_file( SvPVX(filename), "w" );
517             ERR_print_errors(bio);
518             BIO_free(bio);
519              
520             #endif
521              
522             ####################
523