diff options
Diffstat (limited to 'node/EllipticCurveKeyPair.cpp')
-rw-r--r-- | node/EllipticCurveKeyPair.cpp | 369 |
1 files changed, 0 insertions, 369 deletions
diff --git a/node/EllipticCurveKeyPair.cpp b/node/EllipticCurveKeyPair.cpp deleted file mode 100644 index dd95d9a7..00000000 --- a/node/EllipticCurveKeyPair.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* - * ZeroTier One - Global Peer to Peer Ethernet - * Copyright (C) 2012-2013 ZeroTier Networks LLC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * -- - * - * ZeroTier may be used and distributed under the terms of the GPLv3, which - * are available at: http://www.gnu.org/licenses/gpl-3.0.html - * - * If you would like to embed ZeroTier into a commercial application or - * redistribute it in a modified binary form, please contact ZeroTier Networks - * LLC. Start here: http://www.zerotier.com/ - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "Constants.hpp" - -#ifdef __WINDOWS__ -#include <WinSock2.h> -#include <Windows.h> -#endif - -#include <openssl/bn.h> -#include <openssl/obj_mac.h> -#include <openssl/rand.h> -#include <openssl/ec.h> -#include <openssl/ecdh.h> -#include <openssl/ecdsa.h> -#include <openssl/sha.h> - -#include "EllipticCurveKey.hpp" -#include "EllipticCurveKeyPair.hpp" - -namespace ZeroTier { - -class _EC_Group -{ -public: - _EC_Group() - { - g = EC_GROUP_new_by_curve_name(ZT_EC_OPENSSL_CURVE); - } - ~_EC_Group() {} - EC_GROUP *g; -}; -static _EC_Group ZT_EC_GROUP; - -/** - * Key derivation function - * - * TODO: - * If/when we document the protocol, this will have to be documented as - * well. It's a fairly standard KDF that uses SHA-256 to transform the - * raw EC key. It's generally considered good crypto practice to do this - * to eliminate the possibility of leaking information from EC exchange to - * downstream algorithms. - * - * In our code it is used to produce a two 32-bit keys. One key is used - * for Salsa20 and the other for HMAC-SHA-256. They are generated together - * as a single 64-bit key. - */ -static void *_zt_EC_KDF(const void *in,size_t inlen,void *out,size_t *outlen) -{ - SHA256_CTX sha; - unsigned char dig[SHA256_DIGEST_LENGTH]; - - SHA256_Init(&sha); - SHA256_Update(&sha,(const unsigned char *)in,inlen); - SHA256_Final(dig,&sha); - for(unsigned long i=0,k=0;i<(unsigned long)*outlen;) { - if (k == SHA256_DIGEST_LENGTH) { - k = 0; - SHA256_Init(&sha); - SHA256_Update(&sha,(const unsigned char *)in,inlen); - SHA256_Update(&sha,dig,SHA256_DIGEST_LENGTH); - SHA256_Final(dig,&sha); - } - ((unsigned char *)out)[i++] = dig[k++]; - } - - return out; -} - -EllipticCurveKeyPair::EllipticCurveKeyPair() : - _pub(), - _priv(), - _internal_key((void *)0) -{ -} - -EllipticCurveKeyPair::EllipticCurveKeyPair(const EllipticCurveKeyPair &pair) : - _pub(pair._pub), - _priv(pair._priv), - _internal_key((void *)0) -{ -} - -EllipticCurveKeyPair::EllipticCurveKeyPair(const EllipticCurveKey &pubk,const EllipticCurveKey &privk) : - _pub(pubk), - _priv(privk), - _internal_key((void *)0) -{ -} - -EllipticCurveKeyPair::~EllipticCurveKeyPair() -{ - if (_internal_key) - EC_KEY_free((EC_KEY *)_internal_key); -} - -const EllipticCurveKeyPair &EllipticCurveKeyPair::operator=(const EllipticCurveKeyPair &pair) -{ - if (_internal_key) - EC_KEY_free((EC_KEY *)_internal_key); - _pub = pair._pub; - _priv = pair._priv; - _internal_key = (void *)0; - return *this; -} - -bool EllipticCurveKeyPair::generate() -{ - EC_KEY *key; - int len; - - key = EC_KEY_new(); - if (!key) return false; - - if (!EC_KEY_set_group(key,ZT_EC_GROUP.g)) { - EC_KEY_free(key); - return false; - } - - if (!EC_KEY_generate_key(key)) { - EC_KEY_free(key); - return false; - } - - memset(_priv._key,0,sizeof(_priv._key)); - len = (int)BN_num_bytes(EC_KEY_get0_private_key(key)); - if ((len > ZT_EC_PRIME_BYTES)||(len < 0)) { - EC_KEY_free(key); - return false; - } - BN_bn2bin(EC_KEY_get0_private_key(key),&(_priv._key[ZT_EC_PRIME_BYTES - len])); - _priv._bytes = ZT_EC_PRIME_BYTES; - - memset(_pub._key,0,sizeof(_pub._key)); - len = (int)EC_POINT_point2oct(ZT_EC_GROUP.g,EC_KEY_get0_public_key(key),POINT_CONVERSION_COMPRESSED,_pub._key,sizeof(_pub._key),0); - if (len != ZT_EC_PUBLIC_KEY_BYTES) { - EC_KEY_free(key); - return false; - } - _pub._bytes = ZT_EC_PUBLIC_KEY_BYTES; - - if (_internal_key) - EC_KEY_free((EC_KEY *)_internal_key); - _internal_key = key; - - return true; -} - -bool EllipticCurveKeyPair::agree(const EllipticCurveKey &theirPublicKey,unsigned char *agreedUponKey,unsigned int agreedUponKeyLength) const -{ - if (theirPublicKey._bytes != ZT_EC_PUBLIC_KEY_BYTES) - return false; - - if (!_internal_key) { - if (!(const_cast <EllipticCurveKeyPair *> (this))->initInternalKey()) - return false; - } - - EC_POINT *pub = EC_POINT_new(ZT_EC_GROUP.g); - if (!pub) - return false; - EC_POINT_oct2point(ZT_EC_GROUP.g,pub,theirPublicKey._key,ZT_EC_PUBLIC_KEY_BYTES,0); - - int i = ECDH_compute_key(agreedUponKey,agreedUponKeyLength,pub,(EC_KEY *)_internal_key,&_zt_EC_KDF); - EC_POINT_free(pub); - - return (i == (int)agreedUponKeyLength); -} - -std::string EllipticCurveKeyPair::sign(const void *sha256) const -{ - unsigned char buf[256]; - std::string sigbin; - - if (!_internal_key) { - if (!(const_cast <EllipticCurveKeyPair *> (this))->initInternalKey()) - return std::string(); - } - - ECDSA_SIG *sig = ECDSA_do_sign((const unsigned char *)sha256,SHA256_DIGEST_LENGTH,(EC_KEY *)_internal_key); - if (!sig) - return std::string(); - - int rlen = BN_num_bytes(sig->r); - if ((rlen > 255)||(rlen <= 0)) { - ECDSA_SIG_free(sig); - return std::string(); - } - sigbin.push_back((char)rlen); - BN_bn2bin(sig->r,buf); - sigbin.append((const char *)buf,rlen); - - int slen = BN_num_bytes(sig->s); - if ((slen > 255)||(slen <= 0)) { - ECDSA_SIG_free(sig); - return std::string(); - } - sigbin.push_back((char)slen); - BN_bn2bin(sig->s,buf); - sigbin.append((const char *)buf,slen); - - ECDSA_SIG_free(sig); - - return sigbin; -} - -std::string EllipticCurveKeyPair::sign(const void *data,unsigned int len) const -{ - SHA256_CTX sha; - unsigned char dig[SHA256_DIGEST_LENGTH]; - - SHA256_Init(&sha); - SHA256_Update(&sha,(const unsigned char *)data,len); - SHA256_Final(dig,&sha); - - return sign(dig); -} - -bool EllipticCurveKeyPair::verify(const void *sha256,const EllipticCurveKey &pk,const void *sigbytes,unsigned int siglen) -{ - bool result = false; - ECDSA_SIG *sig = (ECDSA_SIG *)0; - EC_POINT *pub = (EC_POINT *)0; - EC_KEY *key = (EC_KEY *)0; - int rlen,slen; - - if (!siglen) - goto verify_sig_return; - rlen = ((const unsigned char *)sigbytes)[0]; - if (!rlen) - goto verify_sig_return; - if (siglen < (unsigned int)(rlen + 2)) - goto verify_sig_return; - slen = ((const unsigned char *)sigbytes)[rlen + 1]; - if (!slen) - goto verify_sig_return; - if (siglen < (unsigned int)(rlen + slen + 2)) - goto verify_sig_return; - - sig = ECDSA_SIG_new(); - if (!sig) - goto verify_sig_return; - - BN_bin2bn((const unsigned char *)sigbytes + 1,rlen,sig->r); - BN_bin2bn((const unsigned char *)sigbytes + (1 + rlen + 1),slen,sig->s); - - pub = EC_POINT_new(ZT_EC_GROUP.g); - if (!pub) - goto verify_sig_return; - EC_POINT_oct2point(ZT_EC_GROUP.g,pub,pk._key,ZT_EC_PUBLIC_KEY_BYTES,0); - - key = EC_KEY_new(); - if (!key) - goto verify_sig_return; - if (!EC_KEY_set_group(key,ZT_EC_GROUP.g)) - goto verify_sig_return; - EC_KEY_set_public_key(key,pub); - - result = (ECDSA_do_verify((const unsigned char *)sha256,SHA256_DIGEST_LENGTH,sig,key) == 1); - -verify_sig_return: - if (key) - EC_KEY_free(key); - if (pub) - EC_POINT_free(pub); - if (sig) - ECDSA_SIG_free(sig); - - return result; -} - -bool EllipticCurveKeyPair::verify(const void *data,unsigned int len,const EllipticCurveKey &pk,const void *sigbytes,unsigned int siglen) -{ - SHA256_CTX sha; - unsigned char dig[SHA256_DIGEST_LENGTH]; - - SHA256_Init(&sha); - SHA256_Update(&sha,(const unsigned char *)data,len); - SHA256_Final(dig,&sha); - - return verify(dig,pk,sigbytes,siglen); -} - -bool EllipticCurveKeyPair::initInternalKey() -{ - EC_KEY *key; - EC_POINT *kxy; - BIGNUM *pn; - - if (_priv._bytes != ZT_EC_PRIME_BYTES) return false; - if (_pub._bytes != ZT_EC_PUBLIC_KEY_BYTES) return false; - - key = EC_KEY_new(); - if (!key) return false; - - if (!EC_KEY_set_group(key,ZT_EC_GROUP.g)) { - EC_KEY_free(key); - return false; - } - - pn = BN_new(); - if (!pn) { - EC_KEY_free(key); - return false; - } - if (!BN_bin2bn(_priv._key,ZT_EC_PRIME_BYTES,pn)) { - BN_free(pn); - EC_KEY_free(key); - return false; - } - if (!EC_KEY_set_private_key(key,pn)) { - BN_free(pn); - EC_KEY_free(key); - return false; - } - BN_free(pn); - - kxy = EC_POINT_new(ZT_EC_GROUP.g); - if (!kxy) { - EC_KEY_free(key); - return false; - } - EC_POINT_oct2point(ZT_EC_GROUP.g,kxy,_pub._key,ZT_EC_PUBLIC_KEY_BYTES,0); - if (!EC_KEY_set_public_key(key,kxy)) { - EC_POINT_free(kxy); - EC_KEY_free(key); - return false; - } - EC_POINT_free(kxy); - - if (_internal_key) - EC_KEY_free((EC_KEY *)_internal_key); - _internal_key = key; - - return true; -} - -} // namespace ZeroTier - |