1 /* 2 * Copyright (c)2019 ZeroTier, Inc. 3 * 4 * Use of this software is governed by the Business Source License included 5 * in the LICENSE.TXT file in the project's root directory. 6 * 7 * Change Date: 2025-01-01 8 * 9 * On the date above, in accordance with the Business Source License, use 10 * of this software will be governed by version 2.0 of the Apache License. 11 */ 12 /****/ 13 14 #ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP 15 #define ZT_CERTIFICATEOFOWNERSHIP_HPP 16 17 #include <stdint.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #include "Constants.hpp" 23 #include "Credential.hpp" 24 #include "C25519.hpp" 25 #include "Address.hpp" 26 #include "Identity.hpp" 27 #include "Buffer.hpp" 28 #include "InetAddress.hpp" 29 #include "MAC.hpp" 30 31 // Max things per CertificateOfOwnership 32 #define ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS 16 33 34 // Maximum size of a thing's value field in bytes 35 #define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16 36 37 namespace ZeroTier { 38 39 class RuntimeEnvironment; 40 41 /** 42 * Certificate indicating ownership of a network identifier 43 */ 44 class CertificateOfOwnership : public Credential 45 { 46 public: credentialType()47 static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; } 48 49 enum Thing 50 { 51 THING_NULL = 0, 52 THING_MAC_ADDRESS = 1, 53 THING_IPV4_ADDRESS = 2, 54 THING_IPV6_ADDRESS = 3 55 }; 56 CertificateOfOwnership()57 CertificateOfOwnership() 58 { 59 memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership)); 60 } 61 CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address & issuedTo,const uint32_t id)62 CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) 63 { 64 memset(reinterpret_cast<void *>(this),0,sizeof(CertificateOfOwnership)); 65 _networkId = nwid; 66 _ts = ts; 67 _id = id; 68 _issuedTo = issuedTo; 69 } 70 networkId() const71 inline uint64_t networkId() const { return _networkId; } timestamp() const72 inline int64_t timestamp() const { return _ts; } id() const73 inline uint32_t id() const { return _id; } thingCount() const74 inline unsigned int thingCount() const { return (unsigned int)_thingCount; } 75 thingType(const unsigned int i) const76 inline Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; } thingValue(const unsigned int i) const77 inline const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; } 78 issuedTo() const79 inline const Address &issuedTo() const { return _issuedTo; } 80 owns(const InetAddress & ip) const81 inline bool owns(const InetAddress &ip) const 82 { 83 if (ip.ss_family == AF_INET) 84 return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4); 85 if (ip.ss_family == AF_INET6) 86 return this->_owns(THING_IPV6_ADDRESS,reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16); 87 return false; 88 } 89 owns(const MAC & mac) const90 inline bool owns(const MAC &mac) const 91 { 92 uint8_t tmp[6]; 93 mac.copyTo(tmp,6); 94 return this->_owns(THING_MAC_ADDRESS,tmp,6); 95 } 96 addThing(const InetAddress & ip)97 inline void addThing(const InetAddress &ip) 98 { 99 if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; 100 if (ip.ss_family == AF_INET) { 101 _thingTypes[_thingCount] = THING_IPV4_ADDRESS; 102 memcpy(_thingValues[_thingCount],&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4); 103 ++_thingCount; 104 } else if (ip.ss_family == AF_INET6) { 105 _thingTypes[_thingCount] = THING_IPV6_ADDRESS; 106 memcpy(_thingValues[_thingCount],reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16); 107 ++_thingCount; 108 } 109 } 110 addThing(const MAC & mac)111 inline void addThing(const MAC &mac) 112 { 113 if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; 114 _thingTypes[_thingCount] = THING_MAC_ADDRESS; 115 mac.copyTo(_thingValues[_thingCount],6); 116 ++_thingCount; 117 } 118 119 /** 120 * @param signer Signing identity, must have private key 121 * @return True if signature was successful 122 */ sign(const Identity & signer)123 inline bool sign(const Identity &signer) 124 { 125 if (signer.hasPrivate()) { 126 Buffer<sizeof(CertificateOfOwnership) + 64> tmp; 127 _signedBy = signer.address(); 128 this->serialize(tmp,true); 129 _signature = signer.sign(tmp.data(),tmp.size()); 130 return true; 131 } 132 return false; 133 } 134 135 /** 136 * @param RR Runtime environment to allow identity lookup for signedBy 137 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call 138 * @return 0 == OK, 1 == waiting for WHOIS, -1 == BAD signature 139 */ 140 int verify(const RuntimeEnvironment *RR,void *tPtr) const; 141 142 template<unsigned int C> serialize(Buffer<C> & b,const bool forSign=false) const143 inline void serialize(Buffer<C> &b,const bool forSign = false) const 144 { 145 if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); 146 147 b.append(_networkId); 148 b.append(_ts); 149 b.append(_flags); 150 b.append(_id); 151 b.append((uint16_t)_thingCount); 152 for(unsigned int i=0,j=_thingCount;i<j;++i) { 153 b.append((uint8_t)_thingTypes[i]); 154 b.append(_thingValues[i],ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE); 155 } 156 157 _issuedTo.appendTo(b); 158 _signedBy.appendTo(b); 159 if (!forSign) { 160 b.append((uint8_t)1); // 1 == Ed25519 161 b.append((uint16_t)ZT_C25519_SIGNATURE_LEN); // length of signature 162 b.append(_signature.data,ZT_C25519_SIGNATURE_LEN); 163 } 164 165 b.append((uint16_t)0); // length of additional fields, currently 0 166 167 if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); 168 } 169 170 template<unsigned int C> deserialize(const Buffer<C> & b,unsigned int startAt=0)171 inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0) 172 { 173 unsigned int p = startAt; 174 175 *this = CertificateOfOwnership(); 176 177 _networkId = b.template at<uint64_t>(p); p += 8; 178 _ts = b.template at<uint64_t>(p); p += 8; 179 _flags = b.template at<uint64_t>(p); p += 8; 180 _id = b.template at<uint32_t>(p); p += 4; 181 _thingCount = b.template at<uint16_t>(p); p += 2; 182 for(unsigned int i=0,j=_thingCount;i<j;++i) { 183 if (i < ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) { 184 _thingTypes[i] = (uint8_t)b[p++]; 185 memcpy(_thingValues[i],b.field(p,ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE),ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE); 186 p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE; 187 } 188 } 189 190 _issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH; 191 _signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH; 192 if (b[p++] == 1) { 193 if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) 194 throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; 195 p += 2; 196 memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); p += ZT_C25519_SIGNATURE_LEN; 197 } else { 198 p += 2 + b.template at<uint16_t>(p); 199 } 200 201 p += 2 + b.template at<uint16_t>(p); 202 if (p > b.size()) 203 throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; 204 205 return (p - startAt); 206 } 207 208 // Provides natural sort order by ID operator <(const CertificateOfOwnership & coo) const209 inline bool operator<(const CertificateOfOwnership &coo) const { return (_id < coo._id); } 210 operator ==(const CertificateOfOwnership & coo) const211 inline bool operator==(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); } operator !=(const CertificateOfOwnership & coo) const212 inline bool operator!=(const CertificateOfOwnership &coo) const { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); } 213 214 private: 215 bool _owns(const Thing &t,const void *v,unsigned int l) const; 216 217 uint64_t _networkId; 218 int64_t _ts; 219 uint64_t _flags; 220 uint32_t _id; 221 uint16_t _thingCount; 222 uint8_t _thingTypes[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS]; 223 uint8_t _thingValues[ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS][ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE]; 224 Address _issuedTo; 225 Address _signedBy; 226 C25519::Signature _signature; 227 }; 228 229 } // namespace ZeroTier 230 231 #endif 232