certificate.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /*
  2. * Copyright (C)2013-2020 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. package zerotier
  14. // #include "../../serviceiocore/GoGlue.h"
  15. // static inline void *_ZT_Certificate_clone2(uintptr_t p) { return (void *)ZT_Certificate_clone((const ZT_Certificate *)p); }
  16. import "C"
  17. import (
  18. "encoding/json"
  19. "fmt"
  20. "unsafe"
  21. )
  22. const (
  23. CertificateSerialNoSize = 48
  24. CertificateMaxStringLength = int(C.ZT_CERTIFICATE_MAX_STRING_LENGTH)
  25. CertificateLocalTrustFlagRootCA = int(C.ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA)
  26. CertificateLocalTrustFlagZeroTierRootSet = int(C.ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ZEROTIER_ROOT_SET)
  27. CertificateUniqueIdTypeNistP384 = int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384)
  28. CertificateUniqueIdTypeNistP384Size = int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE)
  29. CertificateUniqueIdTypeNistP384PrivateSize = int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE)
  30. )
  31. // CertificateName identifies a real-world entity that owns a subject or has signed a certificate.
  32. type CertificateName struct {
  33. SerialNo string `json:"serialNo,omitempty"`
  34. CommonName string `json:"commonName,omitempty"`
  35. StreetAddress string `json:"streetAddress,omitempty"`
  36. Locality string `json:"locality,omitempty"`
  37. Province string `json:"province,omitempty"`
  38. PostalCode string `json:"postalCode,omitempty"`
  39. Country string `json:"country,omitempty"`
  40. Organization string `json:"organization,omitempty"`
  41. Unit string `json:"unit,omitempty"`
  42. Email string `json:"email,omitempty"`
  43. URL string `json:"url,omitempty"`
  44. Host string `json:"host,omitempty"`
  45. }
  46. // CertificateIdentity bundles an identity with an optional locator.
  47. type CertificateIdentity struct {
  48. Identity *Identity `json:"identity,omitempty"`
  49. Locator *Locator `json:"locator,omitempty"`
  50. }
  51. // CertificateNetwork bundles a network ID with the fingerprint of its primary controller.
  52. type CertificateNetwork struct {
  53. ID uint64 `json:"id"`
  54. Controller Fingerprint `json:"controller"`
  55. }
  56. // CertificateSubject contains information about the subject of a certificate.
  57. type CertificateSubject struct {
  58. Timestamp int64 `json:"timestamp"`
  59. Identities []CertificateIdentity `json:"identities,omitempty"`
  60. Networks []CertificateNetwork `json:"networks,omitempty"`
  61. Certificates []Base32Blob `json:"certificates,omitempty"`
  62. UpdateURLs []string `json:"updateURLs,omitempty"`
  63. Name CertificateName `json:"name"`
  64. UniqueID Base32Blob `json:"uniqueId,omitempty"`
  65. UniqueIDProofSignature Base32Blob `json:"uniqueIdProofSignature,omitempty"`
  66. }
  67. // Certificate is a Go reflection of the C ZT_Certificate struct.
  68. type Certificate struct {
  69. SerialNo Base32Blob `json:"serialNo,omitempty"`
  70. Flags uint64 `json:"flags"`
  71. Timestamp int64 `json:"timestamp"`
  72. Validity [2]int64 `json:"validity"`
  73. Subject CertificateSubject `json:"subject"`
  74. Issuer *Identity `json:"issuer,omitempty"`
  75. IssuerName CertificateName `json:"issuerName"`
  76. ExtendedAttributes Base32Blob `json:"extendedAttributes,omitempty"`
  77. MaxPathLength uint `json:"maxPathLength,omitempty"`
  78. CRL []Base32Blob `json:"crl,omitempty"`
  79. Signature Base32Blob `json:"signature,omitempty"`
  80. }
  81. // CertificateSubjectUniqueIDSecret bundles a certificate subject unique ID and its secret key.
  82. type CertificateSubjectUniqueIDSecret struct {
  83. UniqueID Base32Blob `json:"uniqueId,omitempty"`
  84. UniqueIDSecret Base32Blob `json:"uniqueIdSecret,omitempty"`
  85. }
  86. // LocalCertificate combines a certificate with its local trust flags.
  87. type LocalCertificate struct {
  88. Certificate *Certificate `json:"certificate,omitempty"`
  89. LocalTrust uint `json:"localTrust"`
  90. }
  91. func certificateErrorToError(cerr int) error {
  92. switch cerr {
  93. case C.ZT_CERTIFICATE_ERROR_NONE:
  94. return nil
  95. case C.ZT_CERTIFICATE_ERROR_HAVE_NEWER_CERT:
  96. return ErrCertificateHaveNewerCert
  97. case C.ZT_CERTIFICATE_ERROR_INVALID_FORMAT:
  98. return ErrCertificateInvalidFormat
  99. case C.ZT_CERTIFICATE_ERROR_INVALID_IDENTITY:
  100. return ErrCertificateInvalidIdentity
  101. case C.ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE:
  102. return ErrCertificateInvalidPrimarySignature
  103. case C.ZT_CERTIFICATE_ERROR_INVALID_CHAIN:
  104. return ErrCertificateInvalidChain
  105. case C.ZT_CERTIFICATE_ERROR_INVALID_COMPONENT_SIGNATURE:
  106. return ErrCertificateInvalidComponentSignature
  107. case C.ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF:
  108. return ErrCertificateInvalidUniqueIDProof
  109. case C.ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS:
  110. return ErrCertificateMissingRequiredFields
  111. case C.ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW:
  112. return ErrCertificateOutOfValidTimeWindow
  113. }
  114. return ErrInternal
  115. }
  116. // NewCertificateFromBytes decodes a certificate from an encoded byte string.
  117. // Note that this is also used to decode a CSR. When used for a CSR only the
  118. // Subject part of the certificate will contain anything and the rest will be
  119. // blank. If 'verify' is true the certificate will also be verified. If using
  120. // to decode a CSR this should be false as a CSR will not contain a full set
  121. // of fields or a certificate signature.
  122. func NewCertificateFromBytes(cert []byte, verify bool) (*Certificate, error) {
  123. if len(cert) == 0 {
  124. return nil, ErrInvalidParameter
  125. }
  126. var dec unsafe.Pointer
  127. ver := C.int(0)
  128. if verify {
  129. ver = 1
  130. }
  131. cerr := C.ZT_Certificate_decode((**C.ZT_Certificate)(unsafe.Pointer(&dec)), unsafe.Pointer(&cert[0]), C.int(len(cert)), ver)
  132. if cerr != 0 {
  133. return nil, certificateErrorToError(int(cerr))
  134. }
  135. if dec == nil {
  136. return nil, ErrInternal
  137. }
  138. defer C.ZT_Certificate_delete((*C.ZT_Certificate)(dec))
  139. goCert := newCertificateFromCCertificate(dec)
  140. if goCert == nil {
  141. return nil, ErrInternal
  142. }
  143. return goCert, nil
  144. }
  145. // newCertificateFromCCertificate translates a C ZT_Certificate into a Go Certificate.
  146. func newCertificateFromCCertificate(ccptr unsafe.Pointer) *Certificate {
  147. cc := (*C.ZT_Certificate)(ccptr)
  148. c := new(Certificate)
  149. if cc == nil {
  150. return c
  151. }
  152. sn := (*[48]byte)(unsafe.Pointer(&cc.serialNo[0]))[:]
  153. if !allZero(sn) {
  154. var tmp [48]byte
  155. copy(tmp[:], sn)
  156. c.SerialNo = tmp[:]
  157. }
  158. c.Flags = uint64(cc.flags)
  159. c.Timestamp = int64(cc.timestamp)
  160. c.Validity[0] = int64(cc.validity[0])
  161. c.Validity[1] = int64(cc.validity[1])
  162. c.Subject.Timestamp = int64(cc.subject.timestamp)
  163. for i := 0; i < int(cc.subject.identityCount); i++ {
  164. cid := (*C.ZT_Certificate_Identity)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.identities)) + (uintptr(C.sizeof_ZT_Certificate_Identity) * uintptr(i))))
  165. if cid.identity == nil {
  166. return nil
  167. }
  168. id, err := newIdentityFromCIdentity(cid.identity)
  169. if err != nil {
  170. return nil
  171. }
  172. var loc *Locator
  173. if cid.locator != nil {
  174. loc, err = newLocatorFromCLocator(cid.locator, false)
  175. if err != nil {
  176. return nil
  177. }
  178. }
  179. c.Subject.Identities = append(c.Subject.Identities, CertificateIdentity{
  180. Identity: id,
  181. Locator: loc,
  182. })
  183. }
  184. for i := 0; i < int(cc.subject.networkCount); i++ {
  185. cn := (*C.ZT_Certificate_Network)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.networks)) + (uintptr(C.sizeof_ZT_Certificate_Network) * uintptr(i))))
  186. fp := newFingerprintFromCFingerprint(&cn.controller)
  187. if fp == nil {
  188. return nil
  189. }
  190. c.Subject.Networks = append(c.Subject.Networks, CertificateNetwork{
  191. ID: uint64(cn.id),
  192. Controller: *fp,
  193. })
  194. }
  195. for i := 0; i < int(cc.subject.certificateCount); i++ {
  196. csn := *((**[CertificateSerialNoSize]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.certificates)) + (uintptr(i) * pointerSize))))
  197. var tmp [CertificateSerialNoSize]byte
  198. copy(tmp[:], csn[:])
  199. c.Subject.Certificates = append(c.Subject.Certificates, tmp[:])
  200. }
  201. for i := 0; i < int(cc.subject.updateURLCount); i++ {
  202. curl := *((**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.updateURLs)) + (uintptr(i) * pointerSize))))
  203. c.Subject.UpdateURLs = append(c.Subject.UpdateURLs, C.GoString(curl))
  204. }
  205. c.Subject.Name.SerialNo = C.GoString(&cc.subject.name.serialNo[0])
  206. c.Subject.Name.CommonName = C.GoString(&cc.subject.name.commonName[0])
  207. c.Subject.Name.Country = C.GoString(&cc.subject.name.country[0])
  208. c.Subject.Name.Organization = C.GoString(&cc.subject.name.organization[0])
  209. c.Subject.Name.Unit = C.GoString(&cc.subject.name.unit[0])
  210. c.Subject.Name.Locality = C.GoString(&cc.subject.name.locality[0])
  211. c.Subject.Name.Province = C.GoString(&cc.subject.name.province[0])
  212. c.Subject.Name.StreetAddress = C.GoString(&cc.subject.name.streetAddress[0])
  213. c.Subject.Name.PostalCode = C.GoString(&cc.subject.name.postalCode[0])
  214. c.Subject.Name.Email = C.GoString(&cc.subject.name.email[0])
  215. c.Subject.Name.URL = C.GoString(&cc.subject.name.url[0])
  216. c.Subject.Name.Host = C.GoString(&cc.subject.name.host[0])
  217. if cc.subject.uniqueIdSize > 0 {
  218. c.Subject.UniqueID = C.GoBytes(unsafe.Pointer(cc.subject.uniqueId), C.int(cc.subject.uniqueIdSize))
  219. if cc.subject.uniqueIdProofSignatureSize > 0 {
  220. c.Subject.UniqueIDProofSignature = C.GoBytes(unsafe.Pointer(cc.subject.uniqueIdProofSignature), C.int(cc.subject.uniqueIdProofSignatureSize))
  221. }
  222. }
  223. if cc.issuer != nil {
  224. id, err := newIdentityFromCIdentity(cc.issuer)
  225. if err != nil {
  226. return nil
  227. }
  228. c.Issuer = id
  229. }
  230. c.IssuerName.SerialNo = C.GoString(&cc.issuerName.serialNo[0])
  231. c.IssuerName.CommonName = C.GoString(&cc.issuerName.commonName[0])
  232. c.IssuerName.Country = C.GoString(&cc.issuerName.country[0])
  233. c.IssuerName.Organization = C.GoString(&cc.issuerName.organization[0])
  234. c.IssuerName.Unit = C.GoString(&cc.issuerName.unit[0])
  235. c.IssuerName.Locality = C.GoString(&cc.issuerName.locality[0])
  236. c.IssuerName.Province = C.GoString(&cc.issuerName.province[0])
  237. c.IssuerName.StreetAddress = C.GoString(&cc.issuerName.streetAddress[0])
  238. c.IssuerName.PostalCode = C.GoString(&cc.issuerName.postalCode[0])
  239. c.IssuerName.Email = C.GoString(&cc.issuerName.email[0])
  240. c.IssuerName.URL = C.GoString(&cc.issuerName.url[0])
  241. c.IssuerName.Host = C.GoString(&cc.issuerName.host[0])
  242. if cc.extendedAttributesSize > 0 {
  243. c.ExtendedAttributes = C.GoBytes(unsafe.Pointer(cc.extendedAttributes), C.int(cc.extendedAttributesSize))
  244. }
  245. c.MaxPathLength = uint(cc.maxPathLength)
  246. for i := 0; i < int(cc.crlCount); i++ {
  247. csn := *((**[CertificateSerialNoSize]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.crl)) + (uintptr(i) * pointerSize))))
  248. var tmp [CertificateSerialNoSize]byte
  249. copy(tmp[:], csn[:])
  250. c.CRL = append(c.CRL, tmp[:])
  251. }
  252. if cc.signatureSize > 0 {
  253. c.Signature = C.GoBytes(unsafe.Pointer(cc.signature), C.int(cc.signatureSize))
  254. }
  255. return c
  256. }
  257. // deleteCCertificate deletes a ZT_Certificate object returned by Certificate.CCertificate()
  258. func deleteCCertificate(cc unsafe.Pointer) {
  259. C.ZT_Certificate_delete((*C.ZT_Certificate)(cc))
  260. }
  261. // cCertificate creates a C ZT_Certificate structure from the content of a Certificate.
  262. // It must be deleted with deleteCCertificate.
  263. func (c *Certificate) cCertificate() unsafe.Pointer {
  264. var cc C.ZT_Certificate
  265. var subjectIdentities []C.ZT_Certificate_Identity
  266. var subjectNetworks []C.ZT_Certificate_Network
  267. var subjectCertificates []uintptr
  268. var subjectUpdateURLs []uintptr
  269. var subjectUpdateURLsData [][]byte
  270. var crl []uintptr
  271. if len(c.SerialNo) == 48 {
  272. copy((*[CertificateSerialNoSize]byte)(unsafe.Pointer(&cc.serialNo[0]))[:], c.SerialNo)
  273. }
  274. cc.flags = C.uint64_t(c.Flags)
  275. cc.timestamp = C.int64_t(c.Timestamp)
  276. cc.validity[0] = C.int64_t(c.Validity[0])
  277. cc.validity[1] = C.int64_t(c.Validity[1])
  278. cc.subject.timestamp = C.int64_t(c.Subject.Timestamp)
  279. if len(c.Subject.Identities) > 0 {
  280. subjectIdentities = make([]C.ZT_Certificate_Identity, len(c.Subject.Identities))
  281. for i, id := range c.Subject.Identities {
  282. if id.Identity == nil {
  283. return nil
  284. }
  285. subjectIdentities[i].identity = id.Identity.cIdentity()
  286. if id.Locator != nil {
  287. subjectIdentities[i].locator = id.Locator.cl
  288. }
  289. }
  290. cc.subject.identities = &subjectIdentities[0]
  291. cc.subject.identityCount = C.uint(len(subjectIdentities))
  292. }
  293. if len(c.Subject.Networks) > 0 {
  294. subjectNetworks = make([]C.ZT_Certificate_Network, len(c.Subject.Networks))
  295. for i, n := range c.Subject.Networks {
  296. subjectNetworks[i].id = C.uint64_t(n.ID)
  297. subjectNetworks[i].controller.address = C.uint64_t(n.Controller.Address)
  298. if len(n.Controller.Hash) == 48 {
  299. copy((*[48]byte)(unsafe.Pointer(&subjectNetworks[i].controller.hash[0]))[:], n.Controller.Hash)
  300. }
  301. }
  302. cc.subject.networks = &subjectNetworks[0]
  303. cc.subject.networkCount = C.uint(len(subjectNetworks))
  304. }
  305. if len(c.Subject.Certificates) > 0 {
  306. subjectCertificates = make([]uintptr, len(c.Subject.Certificates))
  307. for i, cert := range c.Subject.Certificates {
  308. if len(cert) != CertificateSerialNoSize {
  309. return nil
  310. }
  311. subjectCertificates[i] = uintptr(unsafe.Pointer(&cert[0]))
  312. }
  313. cc.subject.certificates = (**C.uint8_t)(unsafe.Pointer(&subjectCertificates[0]))
  314. cc.subject.certificateCount = C.uint(len(subjectCertificates))
  315. }
  316. if len(c.Subject.UpdateURLs) > 0 {
  317. subjectUpdateURLs = make([]uintptr, len(c.Subject.UpdateURLs))
  318. subjectUpdateURLsData = make([][]byte, len(c.Subject.UpdateURLs))
  319. for i, u := range c.Subject.UpdateURLs {
  320. subjectUpdateURLsData[i] = stringAsZeroTerminatedBytes(u)
  321. subjectUpdateURLs[i] = uintptr(unsafe.Pointer(&subjectUpdateURLsData[0][0]))
  322. }
  323. cc.subject.updateURLs = (**C.char)(unsafe.Pointer(&subjectUpdateURLs[0]))
  324. cc.subject.updateURLCount = C.uint(len(subjectUpdateURLs))
  325. }
  326. cStrCopy(unsafe.Pointer(&cc.subject.name.serialNo[0]), CertificateMaxStringLength+1, c.Subject.Name.SerialNo)
  327. cStrCopy(unsafe.Pointer(&cc.subject.name.commonName[0]), CertificateMaxStringLength+1, c.Subject.Name.CommonName)
  328. cStrCopy(unsafe.Pointer(&cc.subject.name.country[0]), CertificateMaxStringLength+1, c.Subject.Name.Country)
  329. cStrCopy(unsafe.Pointer(&cc.subject.name.organization[0]), CertificateMaxStringLength+1, c.Subject.Name.Organization)
  330. cStrCopy(unsafe.Pointer(&cc.subject.name.unit[0]), CertificateMaxStringLength+1, c.Subject.Name.Unit)
  331. cStrCopy(unsafe.Pointer(&cc.subject.name.locality[0]), CertificateMaxStringLength+1, c.Subject.Name.Locality)
  332. cStrCopy(unsafe.Pointer(&cc.subject.name.province[0]), CertificateMaxStringLength+1, c.Subject.Name.Province)
  333. cStrCopy(unsafe.Pointer(&cc.subject.name.streetAddress[0]), CertificateMaxStringLength+1, c.Subject.Name.StreetAddress)
  334. cStrCopy(unsafe.Pointer(&cc.subject.name.postalCode[0]), CertificateMaxStringLength+1, c.Subject.Name.PostalCode)
  335. cStrCopy(unsafe.Pointer(&cc.subject.name.email[0]), CertificateMaxStringLength+1, c.Subject.Name.Email)
  336. cStrCopy(unsafe.Pointer(&cc.subject.name.url[0]), CertificateMaxStringLength+1, c.Subject.Name.URL)
  337. cStrCopy(unsafe.Pointer(&cc.subject.name.host[0]), CertificateMaxStringLength+1, c.Subject.Name.Host)
  338. if len(c.Subject.UniqueID) > 0 {
  339. cc.subject.uniqueId = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueID[0]))
  340. cc.subject.uniqueIdSize = C.uint(len(c.Subject.UniqueID))
  341. if len(c.Subject.UniqueIDProofSignature) > 0 {
  342. cc.subject.uniqueIdProofSignature = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueIDProofSignature[0]))
  343. cc.subject.uniqueIdProofSignatureSize = C.uint(len(c.Subject.UniqueIDProofSignature))
  344. }
  345. }
  346. if c.Issuer != nil {
  347. cc.issuer = c.Issuer.cIdentity()
  348. }
  349. cStrCopy(unsafe.Pointer(&cc.issuerName.serialNo[0]), CertificateMaxStringLength+1, c.IssuerName.SerialNo)
  350. cStrCopy(unsafe.Pointer(&cc.issuerName.commonName[0]), CertificateMaxStringLength+1, c.IssuerName.CommonName)
  351. cStrCopy(unsafe.Pointer(&cc.issuerName.country[0]), CertificateMaxStringLength+1, c.IssuerName.Country)
  352. cStrCopy(unsafe.Pointer(&cc.issuerName.organization[0]), CertificateMaxStringLength+1, c.IssuerName.Organization)
  353. cStrCopy(unsafe.Pointer(&cc.issuerName.unit[0]), CertificateMaxStringLength+1, c.IssuerName.Unit)
  354. cStrCopy(unsafe.Pointer(&cc.issuerName.locality[0]), CertificateMaxStringLength+1, c.IssuerName.Locality)
  355. cStrCopy(unsafe.Pointer(&cc.issuerName.province[0]), CertificateMaxStringLength+1, c.IssuerName.Province)
  356. cStrCopy(unsafe.Pointer(&cc.issuerName.streetAddress[0]), CertificateMaxStringLength+1, c.IssuerName.StreetAddress)
  357. cStrCopy(unsafe.Pointer(&cc.issuerName.postalCode[0]), CertificateMaxStringLength+1, c.IssuerName.PostalCode)
  358. cStrCopy(unsafe.Pointer(&cc.issuerName.email[0]), CertificateMaxStringLength+1, c.IssuerName.Email)
  359. cStrCopy(unsafe.Pointer(&cc.issuerName.url[0]), CertificateMaxStringLength+1, c.IssuerName.URL)
  360. cStrCopy(unsafe.Pointer(&cc.issuerName.host[0]), CertificateMaxStringLength+1, c.IssuerName.Host)
  361. if len(c.ExtendedAttributes) > 0 {
  362. cc.extendedAttributes = (*C.uint8_t)(unsafe.Pointer(&c.ExtendedAttributes[0]))
  363. cc.extendedAttributesSize = C.uint(len(c.ExtendedAttributes))
  364. }
  365. cc.maxPathLength = C.uint(c.MaxPathLength)
  366. if len(c.CRL) > 0 {
  367. crl = make([]uintptr, len(c.CRL))
  368. for i, cert := range c.CRL {
  369. if len(cert) != CertificateSerialNoSize {
  370. return nil
  371. }
  372. crl[i] = uintptr(unsafe.Pointer(&cert[0]))
  373. }
  374. cc.crl = (**C.uint8_t)(unsafe.Pointer(&crl[0]))
  375. cc.crlCount = C.uint(len(crl))
  376. }
  377. if len(c.Signature) > 0 {
  378. cc.signature = (*C.uint8_t)(unsafe.Pointer(&c.Signature[0]))
  379. cc.signatureSize = C.uint(len(c.Signature))
  380. }
  381. // HACK: pass pointer to cc as uintptr to disable Go's protection against "Go pointers to
  382. // Go pointers," as the C function called here will make a deep clone and then we are going
  383. // to throw away 'cc' and its components.
  384. return unsafe.Pointer(C._ZT_Certificate_clone2(C.uintptr_t(uintptr(unsafe.Pointer(&cc)))))
  385. }
  386. // Marshal encodes this certificate as a byte array (binary format).
  387. func (c *Certificate) Marshal() ([]byte, error) {
  388. cc := c.cCertificate()
  389. if cc == nil {
  390. return nil, ErrInternal
  391. }
  392. defer deleteCCertificate(cc)
  393. var encoded [16384]byte
  394. encodedSize := C.int(16384)
  395. rv := int(C.ZT_Certificate_encode((*C.ZT_Certificate)(cc), unsafe.Pointer(&encoded[0]), &encodedSize))
  396. if rv != 0 {
  397. return nil, fmt.Errorf("Certificate encode error %d", rv)
  398. }
  399. return append(make([]byte, 0, int(encodedSize)), encoded[0:int(encodedSize)]...), nil
  400. }
  401. // Sign signs this certificate and returns a new one with signature and issuer filled out.
  402. // This should only be used after decoding a CSR with NewCertificateFromBytes. The non-subject
  403. // parts of this Certificate, if any, are ignored. A new Certificate is returned with a completed
  404. // signature.
  405. func (c *Certificate) Sign(id *Identity) (*Certificate, error) {
  406. if id == nil || !id.HasPrivate() {
  407. return nil, ErrInvalidParameter
  408. }
  409. ctmp := c.cCertificate()
  410. if ctmp == nil {
  411. return nil, ErrInternal
  412. }
  413. defer deleteCCertificate(ctmp)
  414. var signedCert [16384]byte
  415. signedCertSize := C.int(16384)
  416. rv := int(C.ZT_Certificate_sign((*C.ZT_Certificate)(ctmp), id.cIdentity(), unsafe.Pointer(&signedCert[0]), &signedCertSize))
  417. if rv != 0 {
  418. return nil, fmt.Errorf("signing failed: error %d", rv)
  419. }
  420. return NewCertificateFromBytes(signedCert[0:int(signedCertSize)], true)
  421. }
  422. // Verify returns nil on success or a certificate error if there is a problem with this certificate.
  423. func (c *Certificate) Verify() error {
  424. cc := c.cCertificate()
  425. if cc == nil {
  426. return ErrInternal
  427. }
  428. defer deleteCCertificate(cc)
  429. return certificateErrorToError(int(C.ZT_Certificate_verify((*C.ZT_Certificate)(cc))))
  430. }
  431. // String returns a compact JSON representation of this certificate.
  432. func (c *Certificate) String() string {
  433. j, _ := json.Marshal(c)
  434. return string(j)
  435. }
  436. // JSON returns this certificate as a human-readable indented JSON string.
  437. func (c *Certificate) JSON() string {
  438. j, _ := json.MarshalIndent(c, "", " ")
  439. return string(j)
  440. }
  441. // NewCertificateSubjectUniqueId creates a new certificate subject unique ID and corresponding private key.
  442. // Right now only one type is supported: CertificateUniqueIdTypeNistP384
  443. func NewCertificateSubjectUniqueId(uniqueIdType int) (id []byte, priv []byte, err error) {
  444. if uniqueIdType != CertificateUniqueIdTypeNistP384 {
  445. err = ErrInvalidParameter
  446. return
  447. }
  448. id = make([]byte, int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE))
  449. priv = make([]byte, int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE))
  450. idSize := C.int(len(id))
  451. idPrivateSize := C.int(len(priv))
  452. rv := int(C.ZT_Certificate_newSubjectUniqueId((C.enum_ZT_CertificateUniqueIdType)(uniqueIdType), unsafe.Pointer(&id[0]), &idSize, unsafe.Pointer(&priv[0]), &idPrivateSize))
  453. if rv != 0 {
  454. id = nil
  455. priv = nil
  456. err = fmt.Errorf("error %d", rv)
  457. return
  458. }
  459. if int(idSize) != len(id) || int(idPrivateSize) != len(priv) {
  460. id = nil
  461. priv = nil
  462. err = ErrInvalidParameter
  463. return
  464. }
  465. return
  466. }
  467. // NewCertificateCSR creates a new certificate signing request (CSR) from a certificate subject and optional unique ID.
  468. func NewCertificateCSR(subject *CertificateSubject, uniqueId []byte, uniqueIdPrivate []byte) ([]byte, error) {
  469. var uid unsafe.Pointer
  470. var uidp unsafe.Pointer
  471. if len(uniqueId) > 0 && len(uniqueIdPrivate) > 0 {
  472. uid = unsafe.Pointer(&uniqueId[0])
  473. uidp = unsafe.Pointer(&uniqueIdPrivate[0])
  474. }
  475. var tmp Certificate
  476. tmp.Subject = *subject
  477. ctmp := tmp.cCertificate()
  478. if ctmp == nil {
  479. return nil, ErrInternal
  480. }
  481. defer deleteCCertificate(ctmp)
  482. var csr [16384]byte
  483. csrSize := C.int(16384)
  484. cc := (*C.ZT_Certificate)(ctmp)
  485. rv := int(C.ZT_Certificate_newCSR(&(cc.subject), uid, C.int(len(uniqueId)), uidp, C.int(len(uniqueIdPrivate)), unsafe.Pointer(&csr[0]), &csrSize))
  486. if rv != 0 {
  487. return nil, fmt.Errorf("ZT_Certificate_newCSR() failed: %d", rv)
  488. }
  489. return append(make([]byte, 0, int(csrSize)), csr[0:int(csrSize)]...), nil
  490. }