Lorenz Brun | a4ea9d0 | 2019-10-31 11:40:30 +0100 | [diff] [blame] | 1 | // Copyright 2020 The Monogon Project Authors. |
| 2 | // |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | // |
| 5 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | // you may not use this file except in compliance with the License. |
| 7 | // You may obtain a copy of the License at |
| 8 | // |
| 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | // |
| 11 | // Unless required by applicable law or agreed to in writing, software |
| 12 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | // See the License for the specific language governing permissions and |
| 15 | // limitations under the License. |
| 16 | |
| 17 | // I've fixed this upstream, compat is going away once |
| 18 | // https://go-review.googlesource.com/c/go/+/204046 hits stable |
| 19 | package ca |
| 20 | |
| 21 | import ( |
| 22 | "crypto" |
| 23 | "crypto/x509" |
| 24 | "crypto/x509/pkix" |
| 25 | "encoding/asn1" |
| 26 | "errors" |
| 27 | "io" |
| 28 | "time" |
| 29 | ) |
| 30 | |
| 31 | // Workaround for Go not supporting Ed25519 CRLs |
| 32 | type CompatCertificate x509.Certificate |
| 33 | |
| 34 | var oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} |
| 35 | var oidSignatureEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} |
| 36 | |
| 37 | func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { |
| 38 | sigAlgo.Algorithm = oidSignatureEd25519 |
| 39 | return |
| 40 | } |
| 41 | |
| 42 | // RFC 5280, 4.2.1.1 |
| 43 | type authKeyId struct { |
| 44 | Id []byte `asn1:"optional,tag:0"` |
| 45 | } |
| 46 | |
| 47 | // CreateCRL returns a DER encoded CRL, signed by this Certificate, that |
| 48 | // contains the given list of revoked certificates. |
| 49 | func (c *CompatCertificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { |
| 50 | key, ok := priv.(crypto.Signer) |
| 51 | if !ok { |
| 52 | return nil, errors.New("x509: certificate private key does not implement crypto.Signer") |
| 53 | } |
| 54 | |
| 55 | hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0) |
| 56 | if err != nil { |
| 57 | return nil, err |
| 58 | } |
| 59 | |
| 60 | // Force revocation times to UTC per RFC 5280. |
| 61 | revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts)) |
| 62 | for i, rc := range revokedCerts { |
| 63 | rc.RevocationTime = rc.RevocationTime.UTC() |
| 64 | revokedCertsUTC[i] = rc |
| 65 | } |
| 66 | |
| 67 | tbsCertList := pkix.TBSCertificateList{ |
| 68 | Version: 1, |
| 69 | Signature: signatureAlgorithm, |
| 70 | Issuer: c.Subject.ToRDNSequence(), |
| 71 | ThisUpdate: now.UTC(), |
| 72 | NextUpdate: expiry.UTC(), |
| 73 | RevokedCertificates: revokedCertsUTC, |
| 74 | } |
| 75 | |
| 76 | // Authority Key Id |
| 77 | if len(c.SubjectKeyId) > 0 { |
| 78 | var aki pkix.Extension |
| 79 | aki.Id = oidExtensionAuthorityKeyId |
| 80 | aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId}) |
| 81 | if err != nil { |
| 82 | return |
| 83 | } |
| 84 | tbsCertList.Extensions = append(tbsCertList.Extensions, aki) |
| 85 | } |
| 86 | |
| 87 | tbsCertListContents, err := asn1.Marshal(tbsCertList) |
| 88 | if err != nil { |
| 89 | return |
| 90 | } |
| 91 | |
| 92 | signed := tbsCertListContents |
| 93 | if hashFunc != 0 { |
| 94 | h := hashFunc.New() |
| 95 | h.Write(signed) |
| 96 | signed = h.Sum(nil) |
| 97 | } |
| 98 | |
| 99 | var signature []byte |
| 100 | signature, err = key.Sign(rand, signed, hashFunc) |
| 101 | if err != nil { |
| 102 | return |
| 103 | } |
| 104 | |
| 105 | return asn1.Marshal(pkix.CertificateList{ |
| 106 | TBSCertList: tbsCertList, |
| 107 | SignatureAlgorithm: signatureAlgorithm, |
| 108 | SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, |
| 109 | }) |
| 110 | } |