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