certificate.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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: 2024-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. import "C"
  16. import (
  17. "fmt"
  18. "unsafe"
  19. )
  20. const (
  21. CertificateSerialNoSize = 48
  22. CertificateMaxStringLength = int(C.ZT_CERTIFICATE_MAX_STRING_LENGTH)
  23. CertificateUniqueIdTypeNistP384 = int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384)
  24. )
  25. // CertificateName identifies a real-world entity that owns a subject or has signed a certificate.
  26. type CertificateName struct {
  27. SerialNo string `json:"serialNo,omitempty"`
  28. CommonName string `json:"commonName,omitempty"`
  29. StreetAddress string `json:"streetAddress,omitempty"`
  30. Locality string `json:"locality,omitempty"`
  31. Province string `json:"province,omitempty"`
  32. PostalCode string `json:"postalCode,omitempty"`
  33. Country string `json:"country,omitempty"`
  34. Organization string `json:"organization,omitempty"`
  35. Unit string `json:"unit,omitempty"`
  36. Email string `json:"email,omitempty"`
  37. URL string `json:"url,omitempty"`
  38. Host string `json:"host,omitempty"`
  39. }
  40. // CertificateIdentity bundles an identity with an optional locator.
  41. type CertificateIdentity struct {
  42. Identity *Identity `json:"identity"`
  43. Locator *Locator `json:"locator,omitempty"`
  44. }
  45. // CertificateNetwork bundles a network ID with the fingerprint of its primary controller.
  46. type CertificateNetwork struct {
  47. ID uint64 `json:"id"`
  48. Controller Fingerprint `json:"controller"`
  49. }
  50. // CertificateSubject contains information about the subject of a certificate.
  51. type CertificateSubject struct {
  52. Timestamp int64 `json:"timestamp"`
  53. Identities []CertificateIdentity `json:"identities,omitempty"`
  54. Networks []CertificateNetwork `json:"networks,omitempty"`
  55. Certificates [][]byte `json:"certificates,omitempty"`
  56. UpdateURLs []string `json:"updateURLs,omitempty"`
  57. Name CertificateName `json:"name"`
  58. UniqueID []byte `json:"uniqueId,omitempty"`
  59. UniqueIDProofSignature []byte `json:"uniqueIdProofSignature,omitempty"`
  60. }
  61. // Certificate is a Go reflection of the C ZT_Certificate struct.
  62. type Certificate struct {
  63. SerialNo []byte `json:"serialNo,omitempty"`
  64. Flags uint64 `json:"flags"`
  65. Timestamp int64 `json:"timestamp"`
  66. Validity [2]int64 `json:"validity"`
  67. Subject CertificateSubject `json:"subject"`
  68. Issuer *Identity `json:"issuer,omitempty"`
  69. IssuerName CertificateName `json:"issuerName"`
  70. ExtendedAttributes []byte `json:"extendedAttributes,omitempty"`
  71. MaxPathLength uint `json:"maxPathLength,omitempty"`
  72. Signature []byte `json:"signature,omitempty"`
  73. }
  74. // CCertificate wraps a pointer to a C ZT_Certificate with any related allocated memory.
  75. // Only the 'C' field should be used directly, and only this field is exported.
  76. type CCertificate struct {
  77. C unsafe.Pointer
  78. internalCertificate C.ZT_Certificate
  79. internalSubjectIdentities []C.ZT_Certificate_Identity
  80. internalSubjectNetworks []C.ZT_Certificate_Network
  81. internalSubjectCertificates []uintptr
  82. internalSubjectUpdateURLs []uintptr
  83. internalSubjectUpdateURLsData [][]byte
  84. }
  85. func certificateErrorToError(cerr int) error {
  86. switch cerr {
  87. case C.ZT_CERTIFICATE_ERROR_NONE:
  88. return nil
  89. case C.ZT_CERTIFICATE_ERROR_HAVE_NEWER_CERT:
  90. return ErrCertificateHaveNewerCert
  91. case C.ZT_CERTIFICATE_ERROR_INVALID_FORMAT:
  92. return ErrCertificateInvalidFormat
  93. case C.ZT_CERTIFICATE_ERROR_INVALID_IDENTITY:
  94. return ErrCertificateInvalidIdentity
  95. case C.ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE:
  96. return ErrCertificateInvalidPrimarySignature
  97. case C.ZT_CERTIFICATE_ERROR_INVALID_CHAIN:
  98. return ErrCertificateInvalidChain
  99. case C.ZT_CERTIFICATE_ERROR_INVALID_COMPONENT_SIGNATURE:
  100. return ErrCertificateInvalidComponentSignature
  101. case C.ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF:
  102. return ErrCertificateInvalidUniqueIDProof
  103. case C.ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS:
  104. return ErrCertificateMissingRequiredFields
  105. case C.ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW:
  106. return ErrCertificateOutOfValidTimeWindow
  107. }
  108. return ErrInternal
  109. }
  110. // NewCertificateFromBytes decodes a certificate from an encoded byte string.
  111. // Note that this is also used to decode a CSR. When used for a CSR only the
  112. // Subject part of the certificate will contain anything and the rest will be
  113. // blank. If 'verify' is true the certificate will also be verified. If using
  114. // to decode a CSR this should be false as a CSR will not contain a full set
  115. // of fields or a certificate signature.
  116. func NewCertificateFromBytes(cert []byte, verify bool) (*Certificate, error) {
  117. if len(cert) == 0 {
  118. return nil, ErrInvalidParameter
  119. }
  120. var dec unsafe.Pointer
  121. ver := C.int(0)
  122. if verify {
  123. ver = 1
  124. }
  125. cerr := C.ZT_Certificate_decode((**C.ZT_Certificate)(unsafe.Pointer(&dec)), unsafe.Pointer(&cert[0]), C.int(len(cert)), ver)
  126. if dec != unsafe.Pointer(nil) {
  127. defer C.ZT_Certificate_delete((*C.ZT_Certificate)(dec))
  128. }
  129. if cerr != 0 {
  130. return nil, certificateErrorToError(int(cerr))
  131. }
  132. if dec == unsafe.Pointer(nil) {
  133. return nil, ErrInternal
  134. }
  135. goCert := NewCertificateFromCCertificate(dec)
  136. if goCert == nil {
  137. return nil, ErrInternal
  138. }
  139. return goCert, nil
  140. }
  141. // NewCertificateFromCCertificate translates a C ZT_Certificate into a Go Certificate.
  142. func NewCertificateFromCCertificate(ccptr unsafe.Pointer) *Certificate {
  143. cc := (*C.ZT_Certificate)(ccptr)
  144. c := new(Certificate)
  145. if cc == nil {
  146. return c
  147. }
  148. sn := (*[48]byte)(unsafe.Pointer(&cc.serialNo[0]))[:]
  149. if !allZero(sn) {
  150. var tmp [48]byte
  151. copy(tmp[:], sn)
  152. c.SerialNo = tmp[:]
  153. }
  154. c.Flags = uint64(cc.flags)
  155. c.Timestamp = int64(cc.timestamp)
  156. c.Validity[0] = int64(cc.validity[0])
  157. c.Validity[1] = int64(cc.validity[1])
  158. c.Subject.Timestamp = int64(cc.subject.timestamp)
  159. for i := 0; i < int(cc.subject.identityCount); i++ {
  160. cid := (*C.ZT_Certificate_Identity)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.identities)) + (uintptr(C.sizeof_ZT_Certificate_Identity) * uintptr(i))))
  161. if cid.identity == nil {
  162. return nil
  163. }
  164. id, err := newIdentityFromCIdentity(cid.identity)
  165. if err != nil {
  166. return nil
  167. }
  168. var loc *Locator
  169. if cid.locator != nil {
  170. loc, err = newLocatorFromCLocator(cid.locator, false)
  171. if err != nil {
  172. return nil
  173. }
  174. }
  175. c.Subject.Identities = append(c.Subject.Identities, CertificateIdentity{
  176. Identity: id,
  177. Locator: loc,
  178. })
  179. }
  180. for i := 0; i < int(cc.subject.networkCount); i++ {
  181. cn := (*C.ZT_Certificate_Network)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.networks)) + (uintptr(C.sizeof_ZT_Certificate_Network) * uintptr(i))))
  182. fp := newFingerprintFromCFingerprint(&cn.controller)
  183. if fp == nil {
  184. return nil
  185. }
  186. c.Subject.Networks = append(c.Subject.Networks, CertificateNetwork{
  187. ID: uint64(cn.id),
  188. Controller: *fp,
  189. })
  190. }
  191. for i := 0; i < int(cc.subject.certificateCount); i++ {
  192. csn := *((**[48]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.certificates)) + (uintptr(i) * pointerSize))))
  193. var tmp [48]byte
  194. copy(tmp[:], csn[:])
  195. c.Subject.Certificates = append(c.Subject.Certificates, tmp[:])
  196. }
  197. for i := 0; i < int(cc.subject.updateURLCount); i++ {
  198. curl := *((**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.updateURLs)) + (uintptr(i) * pointerSize))))
  199. c.Subject.UpdateURLs = append(c.Subject.UpdateURLs, C.GoString(curl))
  200. }
  201. c.Subject.Name.SerialNo = C.GoString(&cc.subject.name.serialNo[0])
  202. c.Subject.Name.CommonName = C.GoString(&cc.subject.name.commonName[0])
  203. c.Subject.Name.Country = C.GoString(&cc.subject.name.country[0])
  204. c.Subject.Name.Organization = C.GoString(&cc.subject.name.organization[0])
  205. c.Subject.Name.Unit = C.GoString(&cc.subject.name.unit[0])
  206. c.Subject.Name.Locality = C.GoString(&cc.subject.name.locality[0])
  207. c.Subject.Name.Province = C.GoString(&cc.subject.name.province[0])
  208. c.Subject.Name.StreetAddress = C.GoString(&cc.subject.name.streetAddress[0])
  209. c.Subject.Name.PostalCode = C.GoString(&cc.subject.name.postalCode[0])
  210. c.Subject.Name.Email = C.GoString(&cc.subject.name.email[0])
  211. c.Subject.Name.URL = C.GoString(&cc.subject.name.url[0])
  212. c.Subject.Name.Host = C.GoString(&cc.subject.name.host[0])
  213. if cc.subject.uniqueIdSize > 0 {
  214. c.Subject.UniqueID = C.GoBytes(unsafe.Pointer(cc.subject.uniqueId), C.int(cc.subject.uniqueIdSize))
  215. if cc.subject.uniqueIdProofSignatureSize > 0 {
  216. c.Subject.UniqueIDProofSignature = C.GoBytes(unsafe.Pointer(cc.subject.uniqueIdProofSignature), C.int(cc.subject.uniqueIdProofSignatureSize))
  217. }
  218. }
  219. if cc.issuer != nil {
  220. id, err := newIdentityFromCIdentity(cc.issuer)
  221. if err != nil {
  222. return nil
  223. }
  224. c.Issuer = id
  225. }
  226. c.IssuerName.SerialNo = C.GoString(&cc.issuerName.serialNo[0])
  227. c.IssuerName.CommonName = C.GoString(&cc.issuerName.commonName[0])
  228. c.IssuerName.Country = C.GoString(&cc.issuerName.country[0])
  229. c.IssuerName.Organization = C.GoString(&cc.issuerName.organization[0])
  230. c.IssuerName.Unit = C.GoString(&cc.issuerName.unit[0])
  231. c.IssuerName.Locality = C.GoString(&cc.issuerName.locality[0])
  232. c.IssuerName.Province = C.GoString(&cc.issuerName.province[0])
  233. c.IssuerName.StreetAddress = C.GoString(&cc.issuerName.streetAddress[0])
  234. c.IssuerName.PostalCode = C.GoString(&cc.issuerName.postalCode[0])
  235. c.IssuerName.Email = C.GoString(&cc.issuerName.email[0])
  236. c.IssuerName.URL = C.GoString(&cc.issuerName.url[0])
  237. c.IssuerName.Host = C.GoString(&cc.issuerName.host[0])
  238. if cc.extendedAttributesSize > 0 {
  239. c.ExtendedAttributes = C.GoBytes(unsafe.Pointer(cc.extendedAttributes), C.int(cc.extendedAttributesSize))
  240. }
  241. c.MaxPathLength = uint(cc.maxPathLength)
  242. if cc.signatureSize > 0 {
  243. c.Signature = C.GoBytes(unsafe.Pointer(cc.signature), C.int(cc.signatureSize))
  244. }
  245. return c
  246. }
  247. // CCertificate creates a C ZT_Certificate structure from the content of a Certificate.
  248. //
  249. // This will return nil if an error occurs, which would indicate an invalid C
  250. // structure or one with invalid values.
  251. //
  252. // The returned Go structure bundles this with some objects that have
  253. // to be created to set their pointers in ZT_Certificate. It's easier to
  254. // manage allocation of these in Go and bundle them so Go's GC will clean
  255. // them up automatically when CCertificate is released. Only the 'C' field
  256. // in CCertificate should be directly used. The rest are internal and are
  257. // hidden outside the package.
  258. //
  259. // Ensure that Certificate is not modified until the generated C certificate
  260. // is no longer in use.
  261. func (c *Certificate) CCertificate() *CCertificate {
  262. var cc CCertificate
  263. var ccC *C.ZT_Certificate
  264. cc.C = unsafe.Pointer(&cc.internalCertificate)
  265. ccC = &cc.internalCertificate
  266. if len(c.SerialNo) == 48 {
  267. copy((*[48]byte)(unsafe.Pointer(&ccC.serialNo[0]))[:], c.SerialNo)
  268. }
  269. ccC.flags = C.uint64_t(c.Flags)
  270. ccC.timestamp = C.int64_t(c.Timestamp)
  271. ccC.validity[0] = C.int64_t(c.Validity[0])
  272. ccC.validity[1] = C.int64_t(c.Validity[1])
  273. ccC.subject.timestamp = C.int64_t(c.Subject.Timestamp)
  274. if len(c.Subject.Identities) > 0 {
  275. cc.internalSubjectIdentities = make([]C.ZT_Certificate_Identity, len(c.Subject.Identities))
  276. for i, id := range c.Subject.Identities {
  277. if id.Identity == nil || !id.Identity.initCIdentityPtr() {
  278. return nil
  279. }
  280. cc.internalSubjectIdentities[i].identity = id.Identity.cid
  281. if id.Locator != nil {
  282. cc.internalSubjectIdentities[i].locator = id.Locator.cl
  283. }
  284. }
  285. ccC.subject.identities = &cc.internalSubjectIdentities[0]
  286. ccC.subject.identityCount = C.uint(len(c.Subject.Identities))
  287. }
  288. if len(c.Subject.Networks) > 0 {
  289. cc.internalSubjectNetworks = make([]C.ZT_Certificate_Network, len(c.Subject.Networks))
  290. for i, n := range c.Subject.Networks {
  291. cc.internalSubjectNetworks[i].id = C.uint64_t(n.ID)
  292. cc.internalSubjectNetworks[i].controller.address = C.uint64_t(n.Controller.Address)
  293. if len(n.Controller.Hash) == 48 {
  294. copy((*[48]byte)(unsafe.Pointer(&cc.internalSubjectNetworks[i].controller.hash[0]))[:], n.Controller.Hash)
  295. }
  296. }
  297. ccC.subject.networks = &cc.internalSubjectNetworks[0]
  298. ccC.subject.networkCount = C.uint(len(c.Subject.Networks))
  299. }
  300. if len(c.Subject.Certificates) > 0 {
  301. cc.internalSubjectCertificates = make([]uintptr, len(c.Subject.Certificates))
  302. for i, cert := range c.Subject.Certificates {
  303. if len(cert) != 48 {
  304. return nil
  305. }
  306. cc.internalSubjectCertificates[i] = uintptr(unsafe.Pointer(&cert[0]))
  307. }
  308. ccC.subject.certificates = (**C.uint8_t)(unsafe.Pointer(&cc.internalSubjectCertificates[0]))
  309. ccC.subject.certificateCount = C.uint(len(c.Subject.Certificates))
  310. }
  311. if len(c.Subject.UpdateURLs) > 0 {
  312. cc.internalSubjectUpdateURLs = make([]uintptr, len(c.Subject.UpdateURLs))
  313. cc.internalSubjectUpdateURLsData = make([][]byte, len(c.Subject.UpdateURLs))
  314. for i, u := range c.Subject.UpdateURLs {
  315. cc.internalSubjectUpdateURLsData[i] = stringAsZeroTerminatedBytes(u)
  316. cc.internalSubjectUpdateURLs[i] = uintptr(unsafe.Pointer(&cc.internalSubjectUpdateURLsData[0][0]))
  317. }
  318. ccC.subject.updateURLs = (**C.char)(unsafe.Pointer(&cc.internalSubjectUpdateURLs[0]))
  319. ccC.subject.updateURLCount = C.uint(len(c.Subject.UpdateURLs))
  320. }
  321. cStrCopy(unsafe.Pointer(&ccC.subject.name.serialNo[0]), CertificateMaxStringLength+1, c.Subject.Name.SerialNo)
  322. cStrCopy(unsafe.Pointer(&ccC.subject.name.commonName[0]), CertificateMaxStringLength+1, c.Subject.Name.CommonName)
  323. cStrCopy(unsafe.Pointer(&ccC.subject.name.country[0]), CertificateMaxStringLength+1, c.Subject.Name.Country)
  324. cStrCopy(unsafe.Pointer(&ccC.subject.name.organization[0]), CertificateMaxStringLength+1, c.Subject.Name.Organization)
  325. cStrCopy(unsafe.Pointer(&ccC.subject.name.unit[0]), CertificateMaxStringLength+1, c.Subject.Name.Unit)
  326. cStrCopy(unsafe.Pointer(&ccC.subject.name.locality[0]), CertificateMaxStringLength+1, c.Subject.Name.Locality)
  327. cStrCopy(unsafe.Pointer(&ccC.subject.name.province[0]), CertificateMaxStringLength+1, c.Subject.Name.Province)
  328. cStrCopy(unsafe.Pointer(&ccC.subject.name.streetAddress[0]), CertificateMaxStringLength+1, c.Subject.Name.StreetAddress)
  329. cStrCopy(unsafe.Pointer(&ccC.subject.name.postalCode[0]), CertificateMaxStringLength+1, c.Subject.Name.PostalCode)
  330. cStrCopy(unsafe.Pointer(&ccC.subject.name.email[0]), CertificateMaxStringLength+1, c.Subject.Name.Email)
  331. cStrCopy(unsafe.Pointer(&ccC.subject.name.url[0]), CertificateMaxStringLength+1, c.Subject.Name.URL)
  332. cStrCopy(unsafe.Pointer(&ccC.subject.name.host[0]), CertificateMaxStringLength+1, c.Subject.Name.Host)
  333. if len(c.Subject.UniqueID) > 0 {
  334. ccC.subject.uniqueId = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueID[0]))
  335. ccC.subject.uniqueIdSize = C.uint(len(c.Subject.UniqueID))
  336. if len(c.Subject.UniqueIDProofSignature) > 0 {
  337. ccC.subject.uniqueIdProofSignature = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueIDProofSignature[0]))
  338. ccC.subject.uniqueIdProofSignatureSize = C.uint(len(c.Subject.UniqueIDProofSignature))
  339. }
  340. }
  341. if c.Issuer != nil {
  342. if !c.Issuer.initCIdentityPtr() {
  343. return nil
  344. }
  345. ccC.issuer = c.Issuer.cid
  346. }
  347. cStrCopy(unsafe.Pointer(&ccC.issuerName.serialNo[0]), CertificateMaxStringLength+1, c.IssuerName.SerialNo)
  348. cStrCopy(unsafe.Pointer(&ccC.issuerName.commonName[0]), CertificateMaxStringLength+1, c.IssuerName.CommonName)
  349. cStrCopy(unsafe.Pointer(&ccC.issuerName.country[0]), CertificateMaxStringLength+1, c.IssuerName.Country)
  350. cStrCopy(unsafe.Pointer(&ccC.issuerName.organization[0]), CertificateMaxStringLength+1, c.IssuerName.Organization)
  351. cStrCopy(unsafe.Pointer(&ccC.issuerName.unit[0]), CertificateMaxStringLength+1, c.IssuerName.Unit)
  352. cStrCopy(unsafe.Pointer(&ccC.issuerName.locality[0]), CertificateMaxStringLength+1, c.IssuerName.Locality)
  353. cStrCopy(unsafe.Pointer(&ccC.issuerName.province[0]), CertificateMaxStringLength+1, c.IssuerName.Province)
  354. cStrCopy(unsafe.Pointer(&ccC.issuerName.streetAddress[0]), CertificateMaxStringLength+1, c.IssuerName.StreetAddress)
  355. cStrCopy(unsafe.Pointer(&ccC.issuerName.postalCode[0]), CertificateMaxStringLength+1, c.IssuerName.PostalCode)
  356. cStrCopy(unsafe.Pointer(&ccC.issuerName.email[0]), CertificateMaxStringLength+1, c.IssuerName.Email)
  357. cStrCopy(unsafe.Pointer(&ccC.issuerName.url[0]), CertificateMaxStringLength+1, c.IssuerName.URL)
  358. cStrCopy(unsafe.Pointer(&ccC.issuerName.host[0]), CertificateMaxStringLength+1, c.IssuerName.Host)
  359. if len(c.ExtendedAttributes) > 0 {
  360. ccC.extendedAttributes = (*C.uint8_t)(unsafe.Pointer(&c.ExtendedAttributes[0]))
  361. ccC.extendedAttributesSize = C.uint(len(c.ExtendedAttributes))
  362. }
  363. ccC.maxPathLength = C.uint(c.MaxPathLength)
  364. if len(c.Signature) > 0 {
  365. ccC.signature = (*C.uint8_t)(unsafe.Pointer(&c.Signature[0]))
  366. ccC.signatureSize = C.uint(len(c.Signature))
  367. }
  368. return &cc
  369. }
  370. // Marshal encodes this certificae as a byte array.
  371. func (c *Certificate) Marshal() ([]byte, error) {
  372. cc := c.CCertificate()
  373. if cc == nil {
  374. return nil, ErrInternal
  375. }
  376. var encoded [16384]byte
  377. encodedSize := C.int(16384)
  378. rv := int(C.ZT_Certificate_encode((*C.ZT_Certificate)(cc.C), unsafe.Pointer(&encoded[0]), &encodedSize))
  379. if rv != 0 {
  380. return nil, fmt.Errorf("Certificate encode error %d", rv)
  381. }
  382. return append(make([]byte, 0, int(encodedSize)), encoded[0:int(encodedSize)]...), nil
  383. }
  384. // Verify returns nil on success or a certificate error if there is a problem with this certificate.
  385. func (c *Certificate) Verify() error {
  386. cc := c.CCertificate()
  387. if cc == nil {
  388. return ErrInternal
  389. }
  390. return certificateErrorToError(int(C.ZT_Certificate_verify((*C.ZT_Certificate)(cc.C))))
  391. }
  392. // NewCertificateSubjectUniqueId creates a new certificate subject unique ID and corresponding private key.
  393. // Right now only one type is supported: CertificateUniqueIdTypeNistP384
  394. func NewCertificateSubjectUniqueId(uniqueIdType int) (id []byte, priv []byte, err error) {
  395. if uniqueIdType != CertificateUniqueIdTypeNistP384 {
  396. err = ErrInvalidParameter
  397. return
  398. }
  399. id = make([]byte, int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE))
  400. priv = make([]byte, int(C.ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE))
  401. idSize := C.int(len(id))
  402. idPrivateSize := C.int(len(priv))
  403. if C.ZT_Certificate_newSubjectUniqueId((C.enum_ZT_CertificateUniqueIdType)(uniqueIdType), unsafe.Pointer(&id[0]), &idSize, unsafe.Pointer(&priv[0]), &idPrivateSize) != 0 {
  404. id = nil
  405. priv = nil
  406. err = ErrInvalidParameter
  407. return
  408. }
  409. if int(idSize) != len(id) || int(idPrivateSize) != len(priv) {
  410. id = nil
  411. priv = nil
  412. err = ErrInvalidParameter
  413. return
  414. }
  415. return
  416. }
  417. // NewCertificateCSR creates a new certificate signing request (CSR) from a certificate subject and optional unique ID.
  418. func NewCertificateCSR(subject *CertificateSubject, uniqueId []byte, uniqueIdPrivate []byte) ([]byte, error) {
  419. var tmp Certificate
  420. tmp.Subject = *subject
  421. ctmp := tmp.CCertificate()
  422. if ctmp == nil {
  423. return nil, ErrInternal
  424. }
  425. ccert := (*C.ZT_Certificate)(ctmp.C)
  426. var uid unsafe.Pointer
  427. var uidp unsafe.Pointer
  428. if len(uniqueId) > 0 && len(uniqueIdPrivate) > 0 {
  429. uid = unsafe.Pointer(&uniqueId[0])
  430. uidp = unsafe.Pointer(&uniqueIdPrivate[0])
  431. }
  432. var csr [16384]byte
  433. csrSize := C.int(16384)
  434. rv := int(C.ZT_Certificate_newCSR(&(ccert.subject), uid, C.int(len(uniqueId)), uidp, C.int(len(uniqueIdPrivate)), unsafe.Pointer(&csr[0]), &csrSize))
  435. if rv != 0 {
  436. return nil, fmt.Errorf("newCSR error %d", rv)
  437. }
  438. return append(make([]byte, 0, int(csrSize)), csr[0:int(csrSize)]...), nil
  439. }