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
15package openssl
16
17// #include "shim.h"
18import "C"
19
20import (
21	"errors"
22	"io/ioutil"
23	"math/big"
24	"runtime"
25	"time"
26	"unsafe"
27)
28
29type EVP_MD int
30
31const (
32	EVP_NULL      EVP_MD = iota
33	EVP_MD5       EVP_MD = iota
34	EVP_MD4       EVP_MD = iota
35	EVP_SHA       EVP_MD = iota
36	EVP_SHA1      EVP_MD = iota
37	EVP_DSS       EVP_MD = iota
38	EVP_DSS1      EVP_MD = iota
39	EVP_MDC2      EVP_MD = iota
40	EVP_RIPEMD160 EVP_MD = iota
41	EVP_SHA224    EVP_MD = iota
42	EVP_SHA256    EVP_MD = iota
43	EVP_SHA384    EVP_MD = iota
44	EVP_SHA512    EVP_MD = iota
45)
46
47// X509_Version represents a version on an x509 certificate.
48type X509_Version int
49
50// Specify constants for x509 versions because the standard states that they
51// are represented internally as one lower than the common version name.
52const (
53	X509_V1 X509_Version = 0
54	X509_V3 X509_Version = 2
55)
56
57type Certificate struct {
58	x      *C.X509
59	Issuer *Certificate
60	ref    interface{}
61	pubKey PublicKey
62}
63
64type CertificateInfo struct {
65	Serial       *big.Int
66	Issued       time.Duration
67	Expires      time.Duration
68	Country      string
69	Organization string
70	CommonName   string
71}
72
73type Name struct {
74	name *C.X509_NAME
75}
76
77// Allocate and return a new Name object.
78func NewName() (*Name, error) {
79	n := C.X509_NAME_new()
80	if n == nil {
81		return nil, errors.New("could not create x509 name")
82	}
83	name := &Name{name: n}
84	runtime.SetFinalizer(name, func(n *Name) {
85		C.X509_NAME_free(n.name)
86	})
87	return name, nil
88}
89
90// AddTextEntry appends a text entry to an X509 NAME.
91func (n *Name) AddTextEntry(field, value string) error {
92	cfield := C.CString(field)
93	defer C.free(unsafe.Pointer(cfield))
94	cvalue := (*C.uchar)(unsafe.Pointer(C.CString(value)))
95	defer C.free(unsafe.Pointer(cvalue))
96	ret := C.X509_NAME_add_entry_by_txt(
97		n.name, cfield, C.MBSTRING_ASC, cvalue, -1, -1, 0)
98	if ret != 1 {
99		return errors.New("failed to add x509 name text entry")
100	}
101	return nil
102}
103
104// AddTextEntries allows adding multiple entries to a name in one call.
105func (n *Name) AddTextEntries(entries map[string]string) error {
106	for f, v := range entries {
107		if err := n.AddTextEntry(f, v); err != nil {
108			return err
109		}
110	}
111	return nil
112}
113
114// GetEntry returns a name entry based on NID.  If no entry, then ("", false) is
115// returned.
116func (n *Name) GetEntry(nid NID) (entry string, ok bool) {
117	entrylen := C.X509_NAME_get_text_by_NID(n.name, C.int(nid), nil, 0)
118	if entrylen == -1 {
119		return "", false
120	}
121	buf := (*C.char)(C.malloc(C.size_t(entrylen + 1)))
122	defer C.free(unsafe.Pointer(buf))
123	C.X509_NAME_get_text_by_NID(n.name, C.int(nid), buf, entrylen+1)
124	return C.GoStringN(buf, entrylen), true
125}
126
127// NewCertificate generates a basic certificate based
128// on the provided CertificateInfo struct
129func NewCertificate(info *CertificateInfo, key PublicKey) (*Certificate, error) {
130	c := &Certificate{x: C.X509_new()}
131	runtime.SetFinalizer(c, func(c *Certificate) {
132		C.X509_free(c.x)
133	})
134
135	name, err := c.GetSubjectName()
136	if err != nil {
137		return nil, err
138	}
139	err = name.AddTextEntries(map[string]string{
140		"C":  info.Country,
141		"O":  info.Organization,
142		"CN": info.CommonName,
143	})
144	if err != nil {
145		return nil, err
146	}
147	// self-issue for now
148	if err := c.SetIssuerName(name); err != nil {
149		return nil, err
150	}
151	if err := c.SetSerial(info.Serial); err != nil {
152		return nil, err
153	}
154	if err := c.SetIssueDate(info.Issued); err != nil {
155		return nil, err
156	}
157	if err := c.SetExpireDate(info.Expires); err != nil {
158		return nil, err
159	}
160	if err := c.SetPubKey(key); err != nil {
161		return nil, err
162	}
163	return c, nil
164}
165
166func (c *Certificate) GetSubjectName() (*Name, error) {
167	n := C.X509_get_subject_name(c.x)
168	if n == nil {
169		return nil, errors.New("failed to get subject name")
170	}
171	return &Name{name: n}, nil
172}
173
174func (c *Certificate) GetIssuerName() (*Name, error) {
175	n := C.X509_get_issuer_name(c.x)
176	if n == nil {
177		return nil, errors.New("failed to get issuer name")
178	}
179	return &Name{name: n}, nil
180}
181
182func (c *Certificate) SetSubjectName(name *Name) error {
183	if C.X509_set_subject_name(c.x, name.name) != 1 {
184		return errors.New("failed to set subject name")
185	}
186	return nil
187}
188
189// SetIssuer updates the stored Issuer cert
190// and the internal x509 Issuer Name of a certificate.
191// The stored Issuer reference is used when adding extensions.
192func (c *Certificate) SetIssuer(issuer *Certificate) error {
193	name, err := issuer.GetSubjectName()
194	if err != nil {
195		return err
196	}
197	if err = c.SetIssuerName(name); err != nil {
198		return err
199	}
200	c.Issuer = issuer
201	return nil
202}
203
204// SetIssuerName populates the issuer name of a certificate.
205// Use SetIssuer instead, if possible.
206func (c *Certificate) SetIssuerName(name *Name) error {
207	if C.X509_set_issuer_name(c.x, name.name) != 1 {
208		return errors.New("failed to set subject name")
209	}
210	return nil
211}
212
213// SetSerial sets the serial of a certificate.
214func (c *Certificate) SetSerial(serial *big.Int) error {
215	sno := C.ASN1_INTEGER_new()
216	defer C.ASN1_INTEGER_free(sno)
217	bn := C.BN_new()
218	defer C.BN_free(bn)
219
220	serialBytes := serial.Bytes()
221	if bn = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&serialBytes[0])), C.int(len(serialBytes)), bn); bn == nil {
222		return errors.New("failed to set serial")
223	}
224	if sno = C.BN_to_ASN1_INTEGER(bn, sno); sno == nil {
225		return errors.New("failed to set serial")
226	}
227	if C.X509_set_serialNumber(c.x, sno) != 1 {
228		return errors.New("failed to set serial")
229	}
230	return nil
231}
232
233// SetIssueDate sets the certificate issue date relative to the current time.
234func (c *Certificate) SetIssueDate(when time.Duration) error {
235	offset := C.long(when / time.Second)
236	result := C.X509_gmtime_adj(C.X_X509_get0_notBefore(c.x), offset)
237	if result == nil {
238		return errors.New("failed to set issue date")
239	}
240	return nil
241}
242
243// SetExpireDate sets the certificate issue date relative to the current time.
244func (c *Certificate) SetExpireDate(when time.Duration) error {
245	offset := C.long(when / time.Second)
246	result := C.X509_gmtime_adj(C.X_X509_get0_notAfter(c.x), offset)
247	if result == nil {
248		return errors.New("failed to set expire date")
249	}
250	return nil
251}
252
253// SetPubKey assigns a new public key to a certificate.
254func (c *Certificate) SetPubKey(pubKey PublicKey) error {
255	c.pubKey = pubKey
256	if C.X509_set_pubkey(c.x, pubKey.evpPKey()) != 1 {
257		return errors.New("failed to set public key")
258	}
259	return nil
260}
261
262// Sign a certificate using a private key and a digest name.
263// Accepted digest names are 'sha256', 'sha384', and 'sha512'.
264func (c *Certificate) Sign(privKey PrivateKey, digest EVP_MD) error {
265	switch digest {
266	case EVP_SHA256:
267	case EVP_SHA384:
268	case EVP_SHA512:
269	default:
270		return errors.New("Unsupported digest" +
271			"You're probably looking for 'EVP_SHA256' or 'EVP_SHA512'.")
272	}
273	return c.insecureSign(privKey, digest)
274}
275
276func (c *Certificate) insecureSign(privKey PrivateKey, digest EVP_MD) error {
277	var md *C.EVP_MD = getDigestFunction(digest)
278	if C.X509_sign(c.x, privKey.evpPKey(), md) <= 0 {
279		return errors.New("failed to sign certificate")
280	}
281	return nil
282}
283
284func getDigestFunction(digest EVP_MD) (md *C.EVP_MD) {
285	switch digest {
286	// please don't use these digest functions
287	case EVP_NULL:
288		md = C.X_EVP_md_null()
289	case EVP_MD5:
290		md = C.X_EVP_md5()
291	case EVP_SHA:
292		md = C.X_EVP_sha()
293	case EVP_SHA1:
294		md = C.X_EVP_sha1()
295	case EVP_DSS:
296		md = C.X_EVP_dss()
297	case EVP_DSS1:
298		md = C.X_EVP_dss1()
299	case EVP_RIPEMD160:
300		md = C.X_EVP_ripemd160()
301	case EVP_SHA224:
302		md = C.X_EVP_sha224()
303	// you actually want one of these
304	case EVP_SHA256:
305		md = C.X_EVP_sha256()
306	case EVP_SHA384:
307		md = C.X_EVP_sha384()
308	case EVP_SHA512:
309		md = C.X_EVP_sha512()
310	}
311	return md
312}
313
314// Add an extension to a certificate.
315// Extension constants are NID_* as found in openssl.
316func (c *Certificate) AddExtension(nid NID, value string) error {
317	issuer := c
318	if c.Issuer != nil {
319		issuer = c.Issuer
320	}
321	var ctx C.X509V3_CTX
322	C.X509V3_set_ctx(&ctx, c.x, issuer.x, nil, nil, 0)
323	ex := C.X509V3_EXT_conf_nid(nil, &ctx, C.int(nid), C.CString(value))
324	if ex == nil {
325		return errors.New("failed to create x509v3 extension")
326	}
327	defer C.X509_EXTENSION_free(ex)
328	if C.X509_add_ext(c.x, ex, -1) <= 0 {
329		return errors.New("failed to add x509v3 extension")
330	}
331	return nil
332}
333
334// AddCustomExtension add custom extenstion to the certificate.
335func (c *Certificate) AddCustomExtension(nid NID, value []byte) error {
336	val := (*C.char)(C.CBytes(value))
337	defer C.free(unsafe.Pointer(val))
338	if int(C.add_custom_ext(c.x, C.int(nid), val, C.int(len(value)))) == 0 {
339		return errors.New("Unable to add extension")
340	}
341	return nil
342}
343
344// Wraps AddExtension using a map of NID to text extension.
345// Will return without finishing if it encounters an error.
346func (c *Certificate) AddExtensions(extensions map[NID]string) error {
347	for nid, value := range extensions {
348		if err := c.AddExtension(nid, value); err != nil {
349			return err
350		}
351	}
352	return nil
353}
354
355// LoadCertificateFromPEM loads an X509 certificate from a PEM-encoded block.
356func LoadCertificateFromPEM(pem_block []byte) (*Certificate, error) {
357	if len(pem_block) == 0 {
358		return nil, errors.New("empty pem block")
359	}
360	runtime.LockOSThread()
361	defer runtime.UnlockOSThread()
362	bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
363		C.int(len(pem_block)))
364	cert := C.PEM_read_bio_X509(bio, nil, nil, nil)
365	C.BIO_free(bio)
366	if cert == nil {
367		return nil, errorFromErrorQueue()
368	}
369	x := &Certificate{x: cert}
370	runtime.SetFinalizer(x, func(x *Certificate) {
371		C.X509_free(x.x)
372	})
373	return x, nil
374}
375
376// MarshalPEM converts the X509 certificate to PEM-encoded format
377func (c *Certificate) MarshalPEM() (pem_block []byte, err error) {
378	bio := C.BIO_new(C.BIO_s_mem())
379	if bio == nil {
380		return nil, errors.New("failed to allocate memory BIO")
381	}
382	defer C.BIO_free(bio)
383	if int(C.PEM_write_bio_X509(bio, c.x)) != 1 {
384		return nil, errors.New("failed dumping certificate")
385	}
386	return ioutil.ReadAll(asAnyBio(bio))
387}
388
389// PublicKey returns the public key embedded in the X509 certificate.
390func (c *Certificate) PublicKey() (PublicKey, error) {
391	pkey := C.X509_get_pubkey(c.x)
392	if pkey == nil {
393		return nil, errors.New("no public key found")
394	}
395	key := &pKey{key: pkey}
396	runtime.SetFinalizer(key, func(key *pKey) {
397		C.EVP_PKEY_free(key.key)
398	})
399	return key, nil
400}
401
402// GetSerialNumberHex returns the certificate's serial number in hex format
403func (c *Certificate) GetSerialNumberHex() (serial string) {
404	asn1_i := C.X509_get_serialNumber(c.x)
405	bignum := C.ASN1_INTEGER_to_BN(asn1_i, nil)
406	hex := C.BN_bn2hex(bignum)
407	serial = C.GoString(hex)
408	C.BN_free(bignum)
409	C.X_OPENSSL_free(unsafe.Pointer(hex))
410	return
411}
412
413// GetVersion returns the X509 version of the certificate.
414func (c *Certificate) GetVersion() X509_Version {
415	return X509_Version(C.X_X509_get_version(c.x))
416}
417
418// SetVersion sets the X509 version of the certificate.
419func (c *Certificate) SetVersion(version X509_Version) error {
420	cvers := C.long(version)
421	if C.X_X509_set_version(c.x, cvers) != 1 {
422		return errors.New("failed to set certificate version")
423	}
424	return nil
425}
426
427// GetExtensionValue returns the value of the given NID's extension.
428func (c *Certificate) GetExtensionValue(nid NID) []byte {
429	dataLength := C.int(0)
430	val := C.get_extention(c.x, C.int(nid), &dataLength)
431	return C.GoBytes(unsafe.Pointer(val), dataLength)
432}
433