cert.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Copyright (C) 2017. See AUTHORS.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package openssl
  15. // #include "shim.h"
  16. import "C"
  17. import (
  18. "errors"
  19. "io/ioutil"
  20. "math/big"
  21. "runtime"
  22. "time"
  23. "unsafe"
  24. )
  25. type EVP_MD int
  26. const (
  27. EVP_NULL EVP_MD = iota
  28. EVP_MD5 EVP_MD = iota
  29. EVP_SHA EVP_MD = iota
  30. EVP_SHA1 EVP_MD = iota
  31. EVP_DSS EVP_MD = iota
  32. EVP_DSS1 EVP_MD = iota
  33. EVP_MDC2 EVP_MD = iota
  34. EVP_RIPEMD160 EVP_MD = iota
  35. EVP_SHA224 EVP_MD = iota
  36. EVP_SHA256 EVP_MD = iota
  37. EVP_SHA384 EVP_MD = iota
  38. EVP_SHA512 EVP_MD = iota
  39. )
  40. type Certificate struct {
  41. x *C.X509
  42. Issuer *Certificate
  43. ref interface{}
  44. pubKey PublicKey
  45. }
  46. type CertificateInfo struct {
  47. Serial *big.Int
  48. Issued time.Duration
  49. Expires time.Duration
  50. Country string
  51. Organization string
  52. CommonName string
  53. }
  54. type Name struct {
  55. name *C.X509_NAME
  56. }
  57. // Allocate and return a new Name object.
  58. func NewName() (*Name, error) {
  59. n := C.X509_NAME_new()
  60. if n == nil {
  61. return nil, errors.New("could not create x509 name")
  62. }
  63. name := &Name{name: n}
  64. runtime.SetFinalizer(name, func(n *Name) {
  65. C.X509_NAME_free(n.name)
  66. })
  67. return name, nil
  68. }
  69. // AddTextEntry appends a text entry to an X509 NAME.
  70. func (n *Name) AddTextEntry(field, value string) error {
  71. cfield := C.CString(field)
  72. defer C.free(unsafe.Pointer(cfield))
  73. cvalue := (*C.uchar)(unsafe.Pointer(C.CString(value)))
  74. defer C.free(unsafe.Pointer(cvalue))
  75. ret := C.X509_NAME_add_entry_by_txt(
  76. n.name, cfield, C.MBSTRING_ASC, cvalue, -1, -1, 0)
  77. if ret != 1 {
  78. return errors.New("failed to add x509 name text entry")
  79. }
  80. return nil
  81. }
  82. // AddTextEntries allows adding multiple entries to a name in one call.
  83. func (n *Name) AddTextEntries(entries map[string]string) error {
  84. for f, v := range entries {
  85. if err := n.AddTextEntry(f, v); err != nil {
  86. return err
  87. }
  88. }
  89. return nil
  90. }
  91. // GetEntry returns a name entry based on NID. If no entry, then ("", false) is
  92. // returned.
  93. func (n *Name) GetEntry(nid NID) (entry string, ok bool) {
  94. entrylen := C.X509_NAME_get_text_by_NID(n.name, C.int(nid), nil, 0)
  95. if entrylen == -1 {
  96. return "", false
  97. }
  98. buf := (*C.char)(C.malloc(C.size_t(entrylen + 1)))
  99. defer C.free(unsafe.Pointer(buf))
  100. C.X509_NAME_get_text_by_NID(n.name, C.int(nid), buf, entrylen+1)
  101. return C.GoStringN(buf, entrylen), true
  102. }
  103. // NewCertificate generates a basic certificate based
  104. // on the provided CertificateInfo struct
  105. func NewCertificate(info *CertificateInfo, key PublicKey) (*Certificate, error) {
  106. c := &Certificate{x: C.X509_new()}
  107. runtime.SetFinalizer(c, func(c *Certificate) {
  108. C.X509_free(c.x)
  109. })
  110. name, err := c.GetSubjectName()
  111. if err != nil {
  112. return nil, err
  113. }
  114. err = name.AddTextEntries(map[string]string{
  115. "C": info.Country,
  116. "O": info.Organization,
  117. "CN": info.CommonName,
  118. })
  119. if err != nil {
  120. return nil, err
  121. }
  122. // self-issue for now
  123. if err := c.SetIssuerName(name); err != nil {
  124. return nil, err
  125. }
  126. if err := c.SetSerial(info.Serial); err != nil {
  127. return nil, err
  128. }
  129. if err := c.SetIssueDate(info.Issued); err != nil {
  130. return nil, err
  131. }
  132. if err := c.SetExpireDate(info.Expires); err != nil {
  133. return nil, err
  134. }
  135. if err := c.SetPubKey(key); err != nil {
  136. return nil, err
  137. }
  138. return c, nil
  139. }
  140. func (c *Certificate) GetSubjectName() (*Name, error) {
  141. n := C.X509_get_subject_name(c.x)
  142. if n == nil {
  143. return nil, errors.New("failed to get subject name")
  144. }
  145. return &Name{name: n}, nil
  146. }
  147. func (c *Certificate) GetIssuerName() (*Name, error) {
  148. n := C.X509_get_issuer_name(c.x)
  149. if n == nil {
  150. return nil, errors.New("failed to get issuer name")
  151. }
  152. return &Name{name: n}, nil
  153. }
  154. func (c *Certificate) SetSubjectName(name *Name) error {
  155. if C.X509_set_subject_name(c.x, name.name) != 1 {
  156. return errors.New("failed to set subject name")
  157. }
  158. return nil
  159. }
  160. // SetIssuer updates the stored Issuer cert
  161. // and the internal x509 Issuer Name of a certificate.
  162. // The stored Issuer reference is used when adding extensions.
  163. func (c *Certificate) SetIssuer(issuer *Certificate) error {
  164. name, err := issuer.GetSubjectName()
  165. if err != nil {
  166. return err
  167. }
  168. if err = c.SetIssuerName(name); err != nil {
  169. return err
  170. }
  171. c.Issuer = issuer
  172. return nil
  173. }
  174. // SetIssuerName populates the issuer name of a certificate.
  175. // Use SetIssuer instead, if possible.
  176. func (c *Certificate) SetIssuerName(name *Name) error {
  177. if C.X509_set_issuer_name(c.x, name.name) != 1 {
  178. return errors.New("failed to set subject name")
  179. }
  180. return nil
  181. }
  182. // SetSerial sets the serial of a certificate.
  183. func (c *Certificate) SetSerial(serial *big.Int) error {
  184. sno := C.ASN1_INTEGER_new()
  185. defer C.ASN1_INTEGER_free(sno)
  186. bn := C.BN_new()
  187. defer C.BN_free(bn)
  188. serialBytes := serial.Bytes()
  189. if bn = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&serialBytes[0])), C.int(len(serialBytes)), bn); bn == nil {
  190. return errors.New("failed to set serial")
  191. }
  192. if sno = C.BN_to_ASN1_INTEGER(bn, sno); sno == nil {
  193. return errors.New("failed to set serial")
  194. }
  195. if C.X509_set_serialNumber(c.x, sno) != 1 {
  196. return errors.New("failed to set serial")
  197. }
  198. return nil
  199. }
  200. // SetIssueDate sets the certificate issue date relative to the current time.
  201. func (c *Certificate) SetIssueDate(when time.Duration) error {
  202. offset := C.long(when / time.Second)
  203. result := C.X509_gmtime_adj(C.X_X509_get0_notBefore(c.x), offset)
  204. if result == nil {
  205. return errors.New("failed to set issue date")
  206. }
  207. return nil
  208. }
  209. // SetExpireDate sets the certificate issue date relative to the current time.
  210. func (c *Certificate) SetExpireDate(when time.Duration) error {
  211. offset := C.long(when / time.Second)
  212. result := C.X509_gmtime_adj(C.X_X509_get0_notAfter(c.x), offset)
  213. if result == nil {
  214. return errors.New("failed to set expire date")
  215. }
  216. return nil
  217. }
  218. // SetPubKey assigns a new public key to a certificate.
  219. func (c *Certificate) SetPubKey(pubKey PublicKey) error {
  220. c.pubKey = pubKey
  221. if C.X509_set_pubkey(c.x, pubKey.evpPKey()) != 1 {
  222. return errors.New("failed to set public key")
  223. }
  224. return nil
  225. }
  226. // Sign a certificate using a private key and a digest name.
  227. // Accepted digest names are 'sha256', 'sha384', and 'sha512'.
  228. func (c *Certificate) Sign(privKey PrivateKey, digest EVP_MD) error {
  229. switch digest {
  230. case EVP_SHA256:
  231. case EVP_SHA384:
  232. case EVP_SHA512:
  233. default:
  234. return errors.New("Unsupported digest" +
  235. "You're probably looking for 'EVP_SHA256' or 'EVP_SHA512'.")
  236. }
  237. return c.insecureSign(privKey, digest)
  238. }
  239. func (c *Certificate) insecureSign(privKey PrivateKey, digest EVP_MD) error {
  240. var md *C.EVP_MD = getDigestFunction(digest)
  241. if C.X509_sign(c.x, privKey.evpPKey(), md) <= 0 {
  242. return errors.New("failed to sign certificate")
  243. }
  244. return nil
  245. }
  246. func getDigestFunction(digest EVP_MD) (md *C.EVP_MD) {
  247. switch digest {
  248. // please don't use these digest functions
  249. case EVP_NULL:
  250. md = C.X_EVP_md_null()
  251. case EVP_MD5:
  252. md = C.X_EVP_md5()
  253. case EVP_SHA:
  254. md = C.X_EVP_sha()
  255. case EVP_SHA1:
  256. md = C.X_EVP_sha1()
  257. case EVP_DSS:
  258. md = C.X_EVP_dss()
  259. case EVP_DSS1:
  260. md = C.X_EVP_dss1()
  261. case EVP_RIPEMD160:
  262. md = C.X_EVP_ripemd160()
  263. case EVP_SHA224:
  264. md = C.X_EVP_sha224()
  265. // you actually want one of these
  266. case EVP_SHA256:
  267. md = C.X_EVP_sha256()
  268. case EVP_SHA384:
  269. md = C.X_EVP_sha384()
  270. case EVP_SHA512:
  271. md = C.X_EVP_sha512()
  272. }
  273. return md
  274. }
  275. // Add an extension to a certificate.
  276. // Extension constants are NID_* as found in openssl.
  277. func (c *Certificate) AddExtension(nid NID, value string) error {
  278. issuer := c
  279. if c.Issuer != nil {
  280. issuer = c.Issuer
  281. }
  282. var ctx C.X509V3_CTX
  283. C.X509V3_set_ctx(&ctx, c.x, issuer.x, nil, nil, 0)
  284. ex := C.X509V3_EXT_conf_nid(nil, &ctx, C.int(nid), C.CString(value))
  285. if ex == nil {
  286. return errors.New("failed to create x509v3 extension")
  287. }
  288. defer C.X509_EXTENSION_free(ex)
  289. if C.X509_add_ext(c.x, ex, -1) <= 0 {
  290. return errors.New("failed to add x509v3 extension")
  291. }
  292. return nil
  293. }
  294. // Wraps AddExtension using a map of NID to text extension.
  295. // Will return without finishing if it encounters an error.
  296. func (c *Certificate) AddExtensions(extensions map[NID]string) error {
  297. for nid, value := range extensions {
  298. if err := c.AddExtension(nid, value); err != nil {
  299. return err
  300. }
  301. }
  302. return nil
  303. }
  304. // LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block.
  305. func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) {
  306. if len(pem_block) == 0 {
  307. return nil, errors.New("empty pem block")
  308. }
  309. runtime.LockOSThread()
  310. defer runtime.UnlockOSThread()
  311. bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
  312. C.int(len(pem_block)))
  313. cert := C.PEM_read_bio_X509(bio, nil, nil, nil)
  314. C.BIO_free(bio)
  315. if cert == nil {
  316. return nil, errorFromErrorQueue()
  317. }
  318. x := &Certificate{x: cert}
  319. runtime.SetFinalizer(x, func(x *Certificate) {
  320. C.X509_free(x.x)
  321. })
  322. return x, nil
  323. }
  324. // MarshalPEM converts the X509 certificate to PEM-encoded format
  325. func (c *Certificate) MarshalPEM() (pem_block []byte, err error) {
  326. bio := C.BIO_new(C.BIO_s_mem())
  327. if bio == nil {
  328. return nil, errors.New("failed to allocate memory BIO")
  329. }
  330. defer C.BIO_free(bio)
  331. if int(C.PEM_write_bio_X509(bio, c.x)) != 1 {
  332. return nil, errors.New("failed dumping certificate")
  333. }
  334. return ioutil.ReadAll(asAnyBio(bio))
  335. }
  336. // PublicKey returns the public key embedded in the X509 certificate.
  337. func (c *Certificate) PublicKey() (PublicKey, error) {
  338. pkey := C.X509_get_pubkey(c.x)
  339. if pkey == nil {
  340. return nil, errors.New("no public key found")
  341. }
  342. key := &pKey{key: pkey}
  343. runtime.SetFinalizer(key, func(key *pKey) {
  344. C.EVP_PKEY_free(key.key)
  345. })
  346. return key, nil
  347. }
  348. // GetSerialNumberHex returns the certificate's serial number in hex format
  349. func (c *Certificate) GetSerialNumberHex() (serial string) {
  350. asn1_i := C.X509_get_serialNumber(c.x)
  351. bignum := C.ASN1_INTEGER_to_BN(asn1_i, nil)
  352. hex := C.BN_bn2hex(bignum)
  353. serial = C.GoString(hex)
  354. C.BN_free(bignum)
  355. C.X_OPENSSL_free(unsafe.Pointer(hex))
  356. return
  357. }