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