Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / cloudflare / cfssl / signer / local / local.go
1 // Package local implements certificate signature functionality for CFSSL.
2 package local
3
4 import (
5         "bytes"
6         "crypto"
7         "crypto/rand"
8         "crypto/x509"
9         "crypto/x509/pkix"
10         "encoding/asn1"
11         "encoding/binary"
12         "encoding/hex"
13         "encoding/pem"
14         "errors"
15         "io"
16         "io/ioutil"
17         "math/big"
18         "net"
19         "net/mail"
20         "os"
21
22         "github.com/cloudflare/cfssl/certdb"
23         "github.com/cloudflare/cfssl/config"
24         cferr "github.com/cloudflare/cfssl/errors"
25         "github.com/cloudflare/cfssl/helpers"
26         "github.com/cloudflare/cfssl/info"
27         "github.com/cloudflare/cfssl/log"
28         "github.com/cloudflare/cfssl/signer"
29         "github.com/google/certificate-transparency/go"
30         "github.com/google/certificate-transparency/go/client"
31 )
32
33 // Signer contains a signer that uses the standard library to
34 // support both ECDSA and RSA CA keys.
35 type Signer struct {
36         ca         *x509.Certificate
37         priv       crypto.Signer
38         policy     *config.Signing
39         sigAlgo    x509.SignatureAlgorithm
40         dbAccessor certdb.Accessor
41 }
42
43 // NewSigner creates a new Signer directly from a
44 // private key and certificate, with optional policy.
45 func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.SignatureAlgorithm, policy *config.Signing) (*Signer, error) {
46         if policy == nil {
47                 policy = &config.Signing{
48                         Profiles: map[string]*config.SigningProfile{},
49                         Default:  config.DefaultConfig()}
50         }
51
52         if !policy.Valid() {
53                 return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
54         }
55
56         return &Signer{
57                 ca:      cert,
58                 priv:    priv,
59                 sigAlgo: sigAlgo,
60                 policy:  policy,
61         }, nil
62 }
63
64 // NewSignerFromFile generates a new local signer from a caFile
65 // and a caKey file, both PEM encoded.
66 func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signer, error) {
67         log.Debug("Loading CA: ", caFile)
68         ca, err := ioutil.ReadFile(caFile)
69         if err != nil {
70                 return nil, err
71         }
72         log.Debug("Loading CA key: ", caKeyFile)
73         cakey, err := ioutil.ReadFile(caKeyFile)
74         if err != nil {
75                 return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
76         }
77
78         parsedCa, err := helpers.ParseCertificatePEM(ca)
79         if err != nil {
80                 return nil, err
81         }
82
83         strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
84         password := []byte(strPassword)
85         if strPassword == "" {
86                 password = nil
87         }
88
89         priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password)
90         if err != nil {
91                 log.Debug("Malformed private key %v", err)
92                 return nil, err
93         }
94
95         return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
96 }
97
98 func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile) (cert []byte, err error) {
99         var distPoints = template.CRLDistributionPoints
100         err = signer.FillTemplate(template, s.policy.Default, profile)
101         if distPoints != nil && len(distPoints) > 0 {
102                 template.CRLDistributionPoints = distPoints
103         }
104         if err != nil {
105                 return
106         }
107
108         var initRoot bool
109         if s.ca == nil {
110                 if !template.IsCA {
111                         err = cferr.New(cferr.PolicyError, cferr.InvalidRequest)
112                         return
113                 }
114                 template.DNSNames = nil
115                 template.EmailAddresses = nil
116                 s.ca = template
117                 initRoot = true
118         }
119
120         derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
121         if err != nil {
122                 return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
123         }
124         if initRoot {
125                 s.ca, err = x509.ParseCertificate(derBytes)
126                 if err != nil {
127                         return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
128                 }
129         }
130
131         cert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
132         log.Infof("signed certificate with serial number %d", template.SerialNumber)
133         return
134 }
135
136 // replaceSliceIfEmpty replaces the contents of replaced with newContents if
137 // the slice referenced by replaced is empty
138 func replaceSliceIfEmpty(replaced, newContents *[]string) {
139         if len(*replaced) == 0 {
140                 *replaced = *newContents
141         }
142 }
143
144 // PopulateSubjectFromCSR has functionality similar to Name, except
145 // it fills the fields of the resulting pkix.Name with req's if the
146 // subject's corresponding fields are empty
147 func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name {
148         // if no subject, use req
149         if s == nil {
150                 return req
151         }
152
153         name := s.Name()
154
155         if name.CommonName == "" {
156                 name.CommonName = req.CommonName
157         }
158
159         replaceSliceIfEmpty(&name.Country, &req.Country)
160         replaceSliceIfEmpty(&name.Province, &req.Province)
161         replaceSliceIfEmpty(&name.Locality, &req.Locality)
162         replaceSliceIfEmpty(&name.Organization, &req.Organization)
163         replaceSliceIfEmpty(&name.OrganizationalUnit, &req.OrganizationalUnit)
164         if name.SerialNumber == "" {
165                 name.SerialNumber = req.SerialNumber
166         }
167         return name
168 }
169
170 // OverrideHosts fills template's IPAddresses, EmailAddresses, and DNSNames with the
171 // content of hosts, if it is not nil.
172 func OverrideHosts(template *x509.Certificate, hosts []string) {
173         if hosts != nil {
174                 template.IPAddresses = []net.IP{}
175                 template.EmailAddresses = []string{}
176                 template.DNSNames = []string{}
177         }
178
179         for i := range hosts {
180                 if ip := net.ParseIP(hosts[i]); ip != nil {
181                         template.IPAddresses = append(template.IPAddresses, ip)
182                 } else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil {
183                         template.EmailAddresses = append(template.EmailAddresses, email.Address)
184                 } else {
185                         template.DNSNames = append(template.DNSNames, hosts[i])
186                 }
187         }
188
189 }
190
191 // Sign signs a new certificate based on the PEM-encoded client
192 // certificate or certificate request with the signing profile,
193 // specified by profileName.
194 func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
195         profile, err := signer.Profile(s, req.Profile)
196         if err != nil {
197                 return
198         }
199
200         block, _ := pem.Decode([]byte(req.Request))
201         if block == nil {
202                 return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
203         }
204
205         if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" {
206                 return nil, cferr.Wrap(cferr.CSRError,
207                         cferr.BadRequest, errors.New("not a certificate or csr"))
208         }
209
210         csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes)
211         if err != nil {
212                 return nil, err
213         }
214
215         // Copy out only the fields from the CSR authorized by policy.
216         safeTemplate := x509.Certificate{}
217         // If the profile contains no explicit whitelist, assume that all fields
218         // should be copied from the CSR.
219         if profile.CSRWhitelist == nil {
220                 safeTemplate = *csrTemplate
221         } else {
222                 if profile.CSRWhitelist.Subject {
223                         safeTemplate.Subject = csrTemplate.Subject
224                 }
225                 if profile.CSRWhitelist.PublicKeyAlgorithm {
226                         safeTemplate.PublicKeyAlgorithm = csrTemplate.PublicKeyAlgorithm
227                 }
228                 if profile.CSRWhitelist.PublicKey {
229                         safeTemplate.PublicKey = csrTemplate.PublicKey
230                 }
231                 if profile.CSRWhitelist.SignatureAlgorithm {
232                         safeTemplate.SignatureAlgorithm = csrTemplate.SignatureAlgorithm
233                 }
234                 if profile.CSRWhitelist.DNSNames {
235                         safeTemplate.DNSNames = csrTemplate.DNSNames
236                 }
237                 if profile.CSRWhitelist.IPAddresses {
238                         safeTemplate.IPAddresses = csrTemplate.IPAddresses
239                 }
240                 if profile.CSRWhitelist.EmailAddresses {
241                         safeTemplate.EmailAddresses = csrTemplate.EmailAddresses
242                 }
243         }
244
245         if req.CRLOverride != "" {
246                 safeTemplate.CRLDistributionPoints = []string{req.CRLOverride}
247         }
248
249         if safeTemplate.IsCA {
250                 if !profile.CAConstraint.IsCA {
251                         log.Error("local signer policy disallows issuing CA certificate")
252                         return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
253                 }
254
255                 if s.ca != nil && s.ca.MaxPathLen > 0 {
256                         if safeTemplate.MaxPathLen >= s.ca.MaxPathLen {
257                                 log.Error("local signer certificate disallows CA MaxPathLen extending")
258                                 // do not sign a cert with pathlen > current
259                                 return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
260                         }
261                 } else if s.ca != nil && s.ca.MaxPathLen == 0 && s.ca.MaxPathLenZero {
262                         log.Error("local signer certificate disallows issuing CA certificate")
263                         // signer has pathlen of 0, do not sign more intermediate CAs
264                         return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
265                 }
266         }
267
268         OverrideHosts(&safeTemplate, req.Hosts)
269         safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject)
270
271         // If there is a whitelist, ensure that both the Common Name and SAN DNSNames match
272         if profile.NameWhitelist != nil {
273                 if safeTemplate.Subject.CommonName != "" {
274                         if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
275                                 return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
276                         }
277                 }
278                 for _, name := range safeTemplate.DNSNames {
279                         if profile.NameWhitelist.Find([]byte(name)) == nil {
280                                 return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
281                         }
282                 }
283                 for _, name := range safeTemplate.EmailAddresses {
284                         if profile.NameWhitelist.Find([]byte(name)) == nil {
285                                 return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
286                         }
287                 }
288         }
289
290         if profile.ClientProvidesSerialNumbers {
291                 if req.Serial == nil {
292                         return nil, cferr.New(cferr.CertificateError, cferr.MissingSerial)
293                 }
294                 safeTemplate.SerialNumber = req.Serial
295         } else {
296                 // RFC 5280 4.1.2.2:
297                 // Certificate users MUST be able to handle serialNumber
298                 // values up to 20 octets.  Conforming CAs MUST NOT use
299                 // serialNumber values longer than 20 octets.
300                 //
301                 // If CFSSL is providing the serial numbers, it makes
302                 // sense to use the max supported size.
303                 serialNumber := make([]byte, 20)
304                 _, err = io.ReadFull(rand.Reader, serialNumber)
305                 if err != nil {
306                         return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
307                 }
308
309                 // SetBytes interprets buf as the bytes of a big-endian
310                 // unsigned integer. The leading byte should be masked
311                 // off to ensure it isn't negative.
312                 serialNumber[0] &= 0x7F
313
314                 safeTemplate.SerialNumber = new(big.Int).SetBytes(serialNumber)
315         }
316
317         if len(req.Extensions) > 0 {
318                 for _, ext := range req.Extensions {
319                         oid := asn1.ObjectIdentifier(ext.ID)
320                         if !profile.ExtensionWhitelist[oid.String()] {
321                                 return nil, cferr.New(cferr.CertificateError, cferr.InvalidRequest)
322                         }
323
324                         rawValue, err := hex.DecodeString(ext.Value)
325                         if err != nil {
326                                 return nil, cferr.Wrap(cferr.CertificateError, cferr.InvalidRequest, err)
327                         }
328
329                         safeTemplate.ExtraExtensions = append(safeTemplate.ExtraExtensions, pkix.Extension{
330                                 Id:       oid,
331                                 Critical: ext.Critical,
332                                 Value:    rawValue,
333                         })
334                 }
335         }
336
337         var certTBS = safeTemplate
338
339         if len(profile.CTLogServers) > 0 {
340                 // Add a poison extension which prevents validation
341                 var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
342                 var poisonedPreCert = certTBS
343                 poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension)
344                 cert, err = s.sign(&poisonedPreCert, profile)
345                 if err != nil {
346                         return
347                 }
348
349                 derCert, _ := pem.Decode(cert)
350                 prechain := []ct.ASN1Cert{derCert.Bytes, s.ca.Raw}
351                 var sctList []ct.SignedCertificateTimestamp
352
353                 for _, server := range profile.CTLogServers {
354                         log.Infof("submitting poisoned precertificate to %s", server)
355                         var ctclient = client.New(server, nil)
356                         var resp *ct.SignedCertificateTimestamp
357                         resp, err = ctclient.AddPreChain(prechain)
358                         if err != nil {
359                                 return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
360                         }
361                         sctList = append(sctList, *resp)
362                 }
363
364                 var serializedSCTList []byte
365                 serializedSCTList, err = serializeSCTList(sctList)
366                 if err != nil {
367                         return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
368                 }
369
370                 // Serialize again as an octet string before embedding
371                 serializedSCTList, err = asn1.Marshal(serializedSCTList)
372                 if err != nil {
373                         return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
374                 }
375
376                 var SCTListExtension = pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedSCTList}
377                 certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension)
378         }
379         var signedCert []byte
380         signedCert, err = s.sign(&certTBS, profile)
381         if err != nil {
382                 return nil, err
383         }
384
385         if s.dbAccessor != nil {
386                 var certRecord = certdb.CertificateRecord{
387                         Serial: certTBS.SerialNumber.String(),
388                         // this relies on the specific behavior of x509.CreateCertificate
389                         // which updates certTBS AuthorityKeyId from the signer's SubjectKeyId
390                         AKI:     hex.EncodeToString(certTBS.AuthorityKeyId),
391                         CALabel: req.Label,
392                         Status:  "good",
393                         Expiry:  certTBS.NotAfter,
394                         PEM:     string(signedCert),
395                 }
396
397                 err = s.dbAccessor.InsertCertificate(certRecord)
398                 if err != nil {
399                         return nil, err
400                 }
401                 log.Debug("saved certificate with serial number ", certTBS.SerialNumber)
402         }
403
404         return signedCert, nil
405 }
406
407 func serializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
408         var buf bytes.Buffer
409         for _, sct := range sctList {
410                 sct, err := ct.SerializeSCT(sct)
411                 if err != nil {
412                         return nil, err
413                 }
414                 binary.Write(&buf, binary.BigEndian, uint16(len(sct)))
415                 buf.Write(sct)
416         }
417
418         var sctListLengthField = make([]byte, 2)
419         binary.BigEndian.PutUint16(sctListLengthField, uint16(buf.Len()))
420         return bytes.Join([][]byte{sctListLengthField, buf.Bytes()}, nil), nil
421 }
422
423 // Info return a populated info.Resp struct or an error.
424 func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
425         cert, err := s.Certificate(req.Label, req.Profile)
426         if err != nil {
427                 return
428         }
429
430         profile, err := signer.Profile(s, req.Profile)
431         if err != nil {
432                 return
433         }
434
435         resp = new(info.Resp)
436         if cert.Raw != nil {
437                 resp.Certificate = string(bytes.TrimSpace(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})))
438         }
439         resp.Usage = profile.Usage
440         resp.ExpiryString = profile.ExpiryString
441
442         return
443 }
444
445 // SigAlgo returns the RSA signer's signature algorithm.
446 func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
447         return s.sigAlgo
448 }
449
450 // Certificate returns the signer's certificate.
451 func (s *Signer) Certificate(label, profile string) (*x509.Certificate, error) {
452         cert := *s.ca
453         return &cert, nil
454 }
455
456 // SetPolicy sets the signer's signature policy.
457 func (s *Signer) SetPolicy(policy *config.Signing) {
458         s.policy = policy
459 }
460
461 // SetDBAccessor sets the signers' cert db accessor
462 func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
463         s.dbAccessor = dba
464 }
465
466 // Policy returns the signer's policy.
467 func (s *Signer) Policy() *config.Signing {
468         return s.policy
469 }