Automatically exchange ECDSA keys and upgrade to new authentication protocol.
[tinc] / src / openssl / ecdsa.c
index 000bfaa..43464d8 100644 (file)
@@ -26,8 +26,8 @@
 #include "ecdsa.h"
 #include "utils.h"
 
-// Set ECDSA keys
-
+// Get and set ECDSA keys
+//
 bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p) {
        *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
 
@@ -44,6 +44,18 @@ bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p) {
        return true;
 }
 
+char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
+       unsigned char *pubkey = NULL;
+       int len = i2o_ECPublicKey(*ecdsa, &pubkey);
+
+       char *base64 = malloc(len * 4 / 3 + 5);
+       b64encode(pubkey, base64, len);
+
+       free(pubkey);
+
+       return base64;
+}
+
 // Read PEM ECDSA keys
 
 bool ecdsa_read_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
@@ -70,13 +82,17 @@ size_t ecdsa_size(ecdsa_t *ecdsa) {
        return ECDSA_size(*ecdsa);
 }
 
-// TODO: hash first, standardise output format?
+// TODO: standardise output format?
 
 bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
        unsigned int siglen = ECDSA_size(*ecdsa);
+
+       char hash[SHA512_DIGEST_LENGTH];
+       SHA512(in, len, hash);
+
        memset(sig, 0, siglen);
 
-       if(!ECDSA_sign(0, in, len, sig, &siglen, *ecdsa)) {
+       if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, *ecdsa)) {
                logger(LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL));
                return false;
        }
@@ -91,10 +107,24 @@ bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
 bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
        unsigned int siglen = ECDSA_size(*ecdsa);
 
-       if(!ECDSA_verify(0, in, len, sig, siglen, *ecdsa)) {
+       char hash[SHA512_DIGEST_LENGTH];
+       SHA512(in, len, hash);
+
+       if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, *ecdsa)) {
                logger(LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL));
                return false;
        }
 
        return true;
 }
+
+bool ecdsa_active(ecdsa_t *ecdsa) {
+       return *ecdsa;
+}
+
+void ecdsa_free(ecdsa_t *ecdsa) {
+       if(*ecdsa) {
+               EC_KEY_free(*ecdsa);
+               *ecdsa = NULL;
+       }
+}