1 #include <Rinternals.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <openssl/crypto.h>
5 #include <openssl/bio.h>
6 #include <openssl/evp.h>
7 #include <openssl/pem.h>
8 #include <openssl/hmac.h>
9 #include "utils.h"
10 #include "compatibility.h"
11 
12 SEXP bignum2r(const BIGNUM *val);
13 BIGNUM *r2bignum(SEXP x);
14 
guess_hashfun(int length)15 static const EVP_MD* guess_hashfun(int length){
16   switch(length){
17   case 16:
18     return EVP_md5();
19   case 20:
20     return EVP_sha1();
21   case 24:
22     return EVP_sha224();
23   case 32:
24     return EVP_sha256();
25   case 48:
26     return EVP_sha384();
27   case 64:
28     return EVP_sha512();
29   }
30   return NULL;
31 }
32 
R_hash_sign(SEXP md,SEXP key)33 SEXP R_hash_sign(SEXP md, SEXP key){
34   BIO *mem = BIO_new_mem_buf(RAW(key), LENGTH(key));
35   EVP_PKEY *pkey = d2i_PrivateKey_bio(mem, NULL);
36   BIO_free(mem);
37   bail(!!pkey);
38   EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
39   bail(!!ctx);
40   bail(EVP_PKEY_sign_init(ctx) > 0);
41   //bail(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) >= 0);
42   const EVP_MD *md_func = guess_hashfun(LENGTH(md));
43   bail(!!md_func);
44   bail(EVP_PKEY_CTX_set_signature_md(ctx, md_func) > 0);
45 
46   //detemine buffer length (this is really required, over/under estimate can crash)
47   size_t siglen;
48   bail(EVP_PKEY_sign(ctx, NULL, &siglen, RAW(md), LENGTH(md)) > 0);
49 
50   //calculate signature
51   unsigned char *sig = OPENSSL_malloc(siglen);
52   bail(EVP_PKEY_sign(ctx, sig, &siglen, RAW(md), LENGTH(md)) > 0);
53   EVP_PKEY_CTX_free(ctx);
54   EVP_PKEY_free(pkey);
55   SEXP res = allocVector(RAWSXP, siglen);
56   memcpy(RAW(res), sig, siglen);
57   OPENSSL_free(sig);
58   return res;
59 }
60 
R_hash_verify(SEXP md,SEXP sig,SEXP pubkey)61 SEXP R_hash_verify(SEXP md, SEXP sig, SEXP pubkey){
62   const unsigned char *ptr = RAW(pubkey);
63   EVP_PKEY *pkey = d2i_PUBKEY(NULL, &ptr, LENGTH(pubkey));
64   bail(!!pkey);
65   EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
66   bail(!!ctx);
67   bail(EVP_PKEY_verify_init(ctx) > 0);
68   //bail(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) >= 0);
69   const EVP_MD *md_func = guess_hashfun(LENGTH(md));
70   bail(!!md_func);
71   bail(EVP_PKEY_CTX_set_signature_md(ctx, md_func) > 0);
72   int res = EVP_PKEY_verify(ctx, RAW(sig), LENGTH(sig), RAW(md), LENGTH(md));
73   bail(res >= 0);
74   if(res == 0)
75     error("Verification failed: incorrect signature");
76   EVP_PKEY_CTX_free(ctx);
77   EVP_PKEY_free(pkey);
78   return ScalarLogical(1);
79 }
80 
81 /* Note: DSA and ECDSA signatures have the same ASN.1 structure */
R_parse_ecdsa(SEXP buf)82 SEXP R_parse_ecdsa(SEXP buf){
83   const char *dsanames[] = {"r", "s", ""};
84   const unsigned char *p = RAW(buf);
85   ECDSA_SIG *sig = d2i_ECDSA_SIG(NULL, &p, Rf_length(buf));
86   bail(!!sig);
87   SEXP out = PROTECT(Rf_mkNamed(VECSXP, dsanames));
88   const BIGNUM *r = NULL;
89   const BIGNUM *s = NULL;
90   MY_ECDSA_SIG_get0(sig, &r, &s);
91   SET_VECTOR_ELT(out, 0, bignum2r(r));
92   SET_VECTOR_ELT(out, 1, bignum2r(s));
93   UNPROTECT(1);
94   return out;
95 }
96 
R_write_ecdsa(SEXP r,SEXP s)97 SEXP R_write_ecdsa(SEXP r, SEXP s){
98   ECDSA_SIG *sig = ECDSA_SIG_new();
99   bail(MY_ECDSA_SIG_set0(sig, r2bignum(r), r2bignum(s)));
100   unsigned char *buf = NULL;
101   int siglen = i2d_ECDSA_SIG(sig, &buf);
102   bail(siglen > 0);
103   SEXP res = allocVector(RAWSXP, siglen);
104   memcpy(RAW(res), buf, siglen);
105   free(buf);
106   ECDSA_SIG_free(sig);
107   return res;
108 }
109