certificate.go 20 KB

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