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