12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513 |
- // Copyright 2009 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // Package x509 implements a subset of the X.509 standard.
- //
- // It allows parsing and generating certificates, certificate signing
- // requests, certificate revocation lists, and encoded public and private keys.
- // It provides a certificate verifier, complete with a chain builder.
- //
- // The package targets the X.509 technical profile defined by the IETF (RFC
- // 2459/3280/5280), and as further restricted by the CA/Browser Forum Baseline
- // Requirements. There is minimal support for features outside of these
- // profiles, as the primary goal of the package is to provide compatibility
- // with the publicly trusted TLS certificate ecosystem and its policies and
- // constraints.
- //
- // On macOS and Windows, certificate verification is handled by system APIs, but
- // the package aims to apply consistent validation rules across operating
- // systems.
- package x509
- import (
- "bytes"
- "crypto"
- "crypto/ecdh"
- "crypto/ecdsa"
- "crypto/ed25519"
- "crypto/elliptic"
- "crypto/rsa"
- "crypto/sha1"
- "crypto/x509/pkix"
- "encoding/asn1"
- "encoding/pem"
- "errors"
- "fmt"
- "internal/godebug"
- "io"
- "math/big"
- "net"
- "net/url"
- "strconv"
- "time"
- "unicode"
- // Explicitly import these for their crypto.RegisterHash init side-effects.
- // Keep these as blank imports, even if they're imported above.
- _ "crypto/sha1"
- _ "crypto/sha256"
- _ "crypto/sha512"
- "golang.org/x/crypto/cryptobyte"
- cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
- )
- // pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
- // in RFC 3280.
- type pkixPublicKey struct {
- Algo pkix.AlgorithmIdentifier
- BitString asn1.BitString
- }
- // ParsePKIXPublicKey parses a public key in PKIX, ASN.1 DER form. The encoded
- // public key is a SubjectPublicKeyInfo structure (see RFC 5280, Section 4.1).
- //
- // It returns a *[rsa.PublicKey], *[dsa.PublicKey], *[ecdsa.PublicKey],
- // [ed25519.PublicKey] (not a pointer), or *[ecdh.PublicKey] (for X25519).
- // More types might be supported in the future.
- //
- // This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY".
- func ParsePKIXPublicKey(derBytes []byte) (pub any, err error) {
- var pki publicKeyInfo
- if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil {
- if _, err := asn1.Unmarshal(derBytes, &pkcs1PublicKey{}); err == nil {
- return nil, errors.New("x509: failed to parse public key (use ParsePKCS1PublicKey instead for this key format)")
- }
- return nil, err
- } else if len(rest) != 0 {
- return nil, errors.New("x509: trailing data after ASN.1 of public-key")
- }
- return parsePublicKey(&pki)
- }
- func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) {
- switch pub := pub.(type) {
- case *rsa.PublicKey:
- publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{
- N: pub.N,
- E: pub.E,
- })
- if err != nil {
- return nil, pkix.AlgorithmIdentifier{}, err
- }
- publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
- // This is a NULL parameters value which is required by
- // RFC 3279, Section 2.3.1.
- publicKeyAlgorithm.Parameters = asn1.NullRawValue
- case *ecdsa.PublicKey:
- oid, ok := oidFromNamedCurve(pub.Curve)
- if !ok {
- return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve")
- }
- if !pub.Curve.IsOnCurve(pub.X, pub.Y) {
- return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: invalid elliptic curve public key")
- }
- publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
- publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
- var paramBytes []byte
- paramBytes, err = asn1.Marshal(oid)
- if err != nil {
- return
- }
- publicKeyAlgorithm.Parameters.FullBytes = paramBytes
- case ed25519.PublicKey:
- publicKeyBytes = pub
- publicKeyAlgorithm.Algorithm = oidPublicKeyEd25519
- case *ecdh.PublicKey:
- publicKeyBytes = pub.Bytes()
- if pub.Curve() == ecdh.X25519() {
- publicKeyAlgorithm.Algorithm = oidPublicKeyX25519
- } else {
- oid, ok := oidFromECDHCurve(pub.Curve())
- if !ok {
- return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve")
- }
- publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
- var paramBytes []byte
- paramBytes, err = asn1.Marshal(oid)
- if err != nil {
- return
- }
- publicKeyAlgorithm.Parameters.FullBytes = paramBytes
- }
- default:
- return nil, pkix.AlgorithmIdentifier{}, fmt.Errorf("x509: unsupported public key type: %T", pub)
- }
- return publicKeyBytes, publicKeyAlgorithm, nil
- }
- // MarshalPKIXPublicKey converts a public key to PKIX, ASN.1 DER form.
- // The encoded public key is a SubjectPublicKeyInfo structure
- // (see RFC 5280, Section 4.1).
- //
- // The following key types are currently supported: *[rsa.PublicKey],
- // *[ecdsa.PublicKey], [ed25519.PublicKey] (not a pointer), and *[ecdh.PublicKey].
- // Unsupported key types result in an error.
- //
- // This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY".
- func MarshalPKIXPublicKey(pub any) ([]byte, error) {
- var publicKeyBytes []byte
- var publicKeyAlgorithm pkix.AlgorithmIdentifier
- var err error
- if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil {
- return nil, err
- }
- pkix := pkixPublicKey{
- Algo: publicKeyAlgorithm,
- BitString: asn1.BitString{
- Bytes: publicKeyBytes,
- BitLength: 8 * len(publicKeyBytes),
- },
- }
- ret, _ := asn1.Marshal(pkix)
- return ret, nil
- }
- // These structures reflect the ASN.1 structure of X.509 certificates.:
- type certificate struct {
- TBSCertificate tbsCertificate
- SignatureAlgorithm pkix.AlgorithmIdentifier
- SignatureValue asn1.BitString
- }
- type tbsCertificate struct {
- Raw asn1.RawContent
- Version int `asn1:"optional,explicit,default:0,tag:0"`
- SerialNumber *big.Int
- SignatureAlgorithm pkix.AlgorithmIdentifier
- Issuer asn1.RawValue
- Validity validity
- Subject asn1.RawValue
- PublicKey publicKeyInfo
- UniqueId asn1.BitString `asn1:"optional,tag:1"`
- SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"`
- Extensions []pkix.Extension `asn1:"omitempty,optional,explicit,tag:3"`
- }
- type dsaAlgorithmParameters struct {
- P, Q, G *big.Int
- }
- type validity struct {
- NotBefore, NotAfter time.Time
- }
- type publicKeyInfo struct {
- Raw asn1.RawContent
- Algorithm pkix.AlgorithmIdentifier
- PublicKey asn1.BitString
- }
- // RFC 5280, 4.2.1.1
- type authKeyId struct {
- Id []byte `asn1:"optional,tag:0"`
- }
- type SignatureAlgorithm int
- const (
- UnknownSignatureAlgorithm SignatureAlgorithm = iota
- MD2WithRSA // Unsupported.
- MD5WithRSA // Only supported for signing, not verification.
- SHA1WithRSA // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses.
- SHA256WithRSA
- SHA384WithRSA
- SHA512WithRSA
- DSAWithSHA1 // Unsupported.
- DSAWithSHA256 // Unsupported.
- ECDSAWithSHA1 // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses.
- ECDSAWithSHA256
- ECDSAWithSHA384
- ECDSAWithSHA512
- SHA256WithRSAPSS
- SHA384WithRSAPSS
- SHA512WithRSAPSS
- PureEd25519
- )
- func (algo SignatureAlgorithm) isRSAPSS() bool {
- switch algo {
- case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS:
- return true
- default:
- return false
- }
- }
- func (algo SignatureAlgorithm) String() string {
- for _, details := range signatureAlgorithmDetails {
- if details.algo == algo {
- return details.name
- }
- }
- return strconv.Itoa(int(algo))
- }
- type PublicKeyAlgorithm int
- const (
- UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
- RSA
- DSA // Only supported for parsing.
- ECDSA
- Ed25519
- )
- var publicKeyAlgoName = [...]string{
- RSA: "RSA",
- DSA: "DSA",
- ECDSA: "ECDSA",
- Ed25519: "Ed25519",
- }
- func (algo PublicKeyAlgorithm) String() string {
- if 0 < algo && int(algo) < len(publicKeyAlgoName) {
- return publicKeyAlgoName[algo]
- }
- return strconv.Itoa(int(algo))
- }
- // OIDs for signature algorithms
- //
- // pkcs-1 OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
- //
- // RFC 3279 2.2.1 RSA Signature Algorithms
- //
- // md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
- //
- // md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
- //
- // sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
- //
- // dsaWithSha1 OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
- //
- // RFC 3279 2.2.3 ECDSA Signature Algorithm
- //
- // ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) ansi-x962(10045)
- // signatures(4) ecdsa-with-SHA1(1)}
- //
- // RFC 4055 5 PKCS #1 Version 1.5
- //
- // sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
- //
- // sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
- //
- // sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
- //
- // RFC 5758 3.1 DSA Signature Algorithms
- //
- // dsaWithSha256 OBJECT IDENTIFIER ::= {
- // joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
- // csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
- //
- // RFC 5758 3.2 ECDSA Signature Algorithm
- //
- // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
- //
- // ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
- //
- // ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
- //
- // RFC 8410 3 Curve25519 and Curve448 Algorithm Identifiers
- //
- // id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
- var (
- oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
- oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
- oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
- oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
- oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
- oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
- oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
- oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
- oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
- oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
- oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
- oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
- oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
- oidSignatureEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112}
- oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
- oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
- oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
- oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8}
- // oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA
- // but it's specified by ISO. Microsoft's makecert.exe has been known
- // to produce certificates with this OID.
- oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
- )
- var signatureAlgorithmDetails = []struct {
- algo SignatureAlgorithm
- name string
- oid asn1.ObjectIdentifier
- pubKeyAlgo PublicKeyAlgorithm
- hash crypto.Hash
- }{
- {MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */},
- {MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, RSA, crypto.MD5},
- {SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, RSA, crypto.SHA1},
- {SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1},
- {SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, RSA, crypto.SHA256},
- {SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, RSA, crypto.SHA384},
- {SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, RSA, crypto.SHA512},
- {SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA256},
- {SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA384},
- {SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA512},
- {DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, DSA, crypto.SHA1},
- {DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, DSA, crypto.SHA256},
- {ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1},
- {ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256},
- {ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384},
- {ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512},
- {PureEd25519, "Ed25519", oidSignatureEd25519, Ed25519, crypto.Hash(0) /* no pre-hashing */},
- }
- // hashToPSSParameters contains the DER encoded RSA PSS parameters for the
- // SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3.
- // The parameters contain the following values:
- // - hashAlgorithm contains the associated hash identifier with NULL parameters
- // - maskGenAlgorithm always contains the default mgf1SHA1 identifier
- // - saltLength contains the length of the associated hash
- // - trailerField always contains the default trailerFieldBC value
- var hashToPSSParameters = map[crypto.Hash]asn1.RawValue{
- crypto.SHA256: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 162, 3, 2, 1, 32}},
- crypto.SHA384: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 162, 3, 2, 1, 48}},
- crypto.SHA512: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 162, 3, 2, 1, 64}},
- }
- // pssParameters reflects the parameters in an AlgorithmIdentifier that
- // specifies RSA PSS. See RFC 3447, Appendix A.2.3.
- type pssParameters struct {
- // The following three fields are not marked as
- // optional because the default values specify SHA-1,
- // which is no longer suitable for use in signatures.
- Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"`
- MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"`
- SaltLength int `asn1:"explicit,tag:2"`
- TrailerField int `asn1:"optional,explicit,tag:3,default:1"`
- }
- func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm {
- if ai.Algorithm.Equal(oidSignatureEd25519) {
- // RFC 8410, Section 3
- // > For all of the OIDs, the parameters MUST be absent.
- if len(ai.Parameters.FullBytes) != 0 {
- return UnknownSignatureAlgorithm
- }
- }
- if !ai.Algorithm.Equal(oidSignatureRSAPSS) {
- for _, details := range signatureAlgorithmDetails {
- if ai.Algorithm.Equal(details.oid) {
- return details.algo
- }
- }
- return UnknownSignatureAlgorithm
- }
- // RSA PSS is special because it encodes important parameters
- // in the Parameters.
- var params pssParameters
- if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, ¶ms); err != nil {
- return UnknownSignatureAlgorithm
- }
- var mgf1HashFunc pkix.AlgorithmIdentifier
- if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil {
- return UnknownSignatureAlgorithm
- }
- // PSS is greatly overburdened with options. This code forces them into
- // three buckets by requiring that the MGF1 hash function always match the
- // message hash function (as recommended in RFC 3447, Section 8.1), that the
- // salt length matches the hash length, and that the trailer field has the
- // default value.
- if (len(params.Hash.Parameters.FullBytes) != 0 && !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes)) ||
- !params.MGF.Algorithm.Equal(oidMGF1) ||
- !mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) ||
- (len(mgf1HashFunc.Parameters.FullBytes) != 0 && !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes)) ||
- params.TrailerField != 1 {
- return UnknownSignatureAlgorithm
- }
- switch {
- case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32:
- return SHA256WithRSAPSS
- case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48:
- return SHA384WithRSAPSS
- case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64:
- return SHA512WithRSAPSS
- }
- return UnknownSignatureAlgorithm
- }
- var (
- // RFC 3279, 2.3 Public Key Algorithms
- //
- // pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
- // rsadsi(113549) pkcs(1) 1 }
- //
- // rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 }
- //
- // id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
- // x9-57(10040) x9cm(4) 1 }
- oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
- oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
- // RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
- //
- // id-ecPublicKey OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
- oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
- // RFC 8410, Section 3
- //
- // id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 }
- // id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
- oidPublicKeyX25519 = asn1.ObjectIdentifier{1, 3, 101, 110}
- oidPublicKeyEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112}
- )
- // getPublicKeyAlgorithmFromOID returns the exposed PublicKeyAlgorithm
- // identifier for public key types supported in certificates and CSRs. Marshal
- // and Parse functions may support a different set of public key types.
- func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm {
- switch {
- case oid.Equal(oidPublicKeyRSA):
- return RSA
- case oid.Equal(oidPublicKeyDSA):
- return DSA
- case oid.Equal(oidPublicKeyECDSA):
- return ECDSA
- case oid.Equal(oidPublicKeyEd25519):
- return Ed25519
- }
- return UnknownPublicKeyAlgorithm
- }
- // RFC 5480, 2.1.1.1. Named Curve
- //
- // secp224r1 OBJECT IDENTIFIER ::= {
- // iso(1) identified-organization(3) certicom(132) curve(0) 33 }
- //
- // secp256r1 OBJECT IDENTIFIER ::= {
- // iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
- // prime(1) 7 }
- //
- // secp384r1 OBJECT IDENTIFIER ::= {
- // iso(1) identified-organization(3) certicom(132) curve(0) 34 }
- //
- // secp521r1 OBJECT IDENTIFIER ::= {
- // iso(1) identified-organization(3) certicom(132) curve(0) 35 }
- //
- // NB: secp256r1 is equivalent to prime256v1
- var (
- oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
- oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
- oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
- oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
- )
- func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
- switch {
- case oid.Equal(oidNamedCurveP224):
- return elliptic.P224()
- case oid.Equal(oidNamedCurveP256):
- return elliptic.P256()
- case oid.Equal(oidNamedCurveP384):
- return elliptic.P384()
- case oid.Equal(oidNamedCurveP521):
- return elliptic.P521()
- }
- return nil
- }
- func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
- switch curve {
- case elliptic.P224():
- return oidNamedCurveP224, true
- case elliptic.P256():
- return oidNamedCurveP256, true
- case elliptic.P384():
- return oidNamedCurveP384, true
- case elliptic.P521():
- return oidNamedCurveP521, true
- }
- return nil, false
- }
- func oidFromECDHCurve(curve ecdh.Curve) (asn1.ObjectIdentifier, bool) {
- switch curve {
- case ecdh.X25519():
- return oidPublicKeyX25519, true
- case ecdh.P256():
- return oidNamedCurveP256, true
- case ecdh.P384():
- return oidNamedCurveP384, true
- case ecdh.P521():
- return oidNamedCurveP521, true
- }
- return nil, false
- }
- // KeyUsage represents the set of actions that are valid for a given key. It's
- // a bitmap of the KeyUsage* constants.
- type KeyUsage int
- const (
- KeyUsageDigitalSignature KeyUsage = 1 << iota
- KeyUsageContentCommitment
- KeyUsageKeyEncipherment
- KeyUsageDataEncipherment
- KeyUsageKeyAgreement
- KeyUsageCertSign
- KeyUsageCRLSign
- KeyUsageEncipherOnly
- KeyUsageDecipherOnly
- )
- // RFC 5280, 4.2.1.12 Extended Key Usage
- //
- // anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
- //
- // id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
- //
- // id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
- // id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
- // id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
- // id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
- // id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
- // id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
- var (
- oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
- oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
- oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
- oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
- oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
- oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
- oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
- oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
- oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
- oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
- oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
- oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
- oidExtKeyUsageMicrosoftCommercialCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 2, 1, 22}
- oidExtKeyUsageMicrosoftKernelCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1}
- )
- // ExtKeyUsage represents an extended set of actions that are valid for a given key.
- // Each of the ExtKeyUsage* constants define a unique action.
- type ExtKeyUsage int
- const (
- ExtKeyUsageAny ExtKeyUsage = iota
- ExtKeyUsageServerAuth
- ExtKeyUsageClientAuth
- ExtKeyUsageCodeSigning
- ExtKeyUsageEmailProtection
- ExtKeyUsageIPSECEndSystem
- ExtKeyUsageIPSECTunnel
- ExtKeyUsageIPSECUser
- ExtKeyUsageTimeStamping
- ExtKeyUsageOCSPSigning
- ExtKeyUsageMicrosoftServerGatedCrypto
- ExtKeyUsageNetscapeServerGatedCrypto
- ExtKeyUsageMicrosoftCommercialCodeSigning
- ExtKeyUsageMicrosoftKernelCodeSigning
- )
- // extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
- var extKeyUsageOIDs = []struct {
- extKeyUsage ExtKeyUsage
- oid asn1.ObjectIdentifier
- }{
- {ExtKeyUsageAny, oidExtKeyUsageAny},
- {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
- {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
- {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
- {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
- {ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
- {ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
- {ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
- {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
- {ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
- {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto},
- {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto},
- {ExtKeyUsageMicrosoftCommercialCodeSigning, oidExtKeyUsageMicrosoftCommercialCodeSigning},
- {ExtKeyUsageMicrosoftKernelCodeSigning, oidExtKeyUsageMicrosoftKernelCodeSigning},
- }
- func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
- for _, pair := range extKeyUsageOIDs {
- if oid.Equal(pair.oid) {
- return pair.extKeyUsage, true
- }
- }
- return
- }
- func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
- for _, pair := range extKeyUsageOIDs {
- if eku == pair.extKeyUsage {
- return pair.oid, true
- }
- }
- return
- }
- // A Certificate represents an X.509 certificate.
- type Certificate struct {
- Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
- RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
- RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
- RawSubject []byte // DER encoded Subject
- RawIssuer []byte // DER encoded Issuer
- Signature []byte
- SignatureAlgorithm SignatureAlgorithm
- PublicKeyAlgorithm PublicKeyAlgorithm
- PublicKey any
- Version int
- SerialNumber *big.Int
- Issuer pkix.Name
- Subject pkix.Name
- NotBefore, NotAfter time.Time // Validity bounds.
- KeyUsage KeyUsage
- // Extensions contains raw X.509 extensions. When parsing certificates,
- // this can be used to extract non-critical extensions that are not
- // parsed by this package. When marshaling certificates, the Extensions
- // field is ignored, see ExtraExtensions.
- Extensions []pkix.Extension
- // ExtraExtensions contains extensions to be copied, raw, into any
- // marshaled certificates. Values override any extensions that would
- // otherwise be produced based on the other fields. The ExtraExtensions
- // field is not populated when parsing certificates, see Extensions.
- ExtraExtensions []pkix.Extension
- // UnhandledCriticalExtensions contains a list of extension IDs that
- // were not (fully) processed when parsing. Verify will fail if this
- // slice is non-empty, unless verification is delegated to an OS
- // library which understands all the critical extensions.
- //
- // Users can access these extensions using Extensions and can remove
- // elements from this slice if they believe that they have been
- // handled.
- UnhandledCriticalExtensions []asn1.ObjectIdentifier
- ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
- UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
- // BasicConstraintsValid indicates whether IsCA, MaxPathLen,
- // and MaxPathLenZero are valid.
- BasicConstraintsValid bool
- IsCA bool
- // MaxPathLen and MaxPathLenZero indicate the presence and
- // value of the BasicConstraints' "pathLenConstraint".
- //
- // When parsing a certificate, a positive non-zero MaxPathLen
- // means that the field was specified, -1 means it was unset,
- // and MaxPathLenZero being true mean that the field was
- // explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false
- // should be treated equivalent to -1 (unset).
- //
- // When generating a certificate, an unset pathLenConstraint
- // can be requested with either MaxPathLen == -1 or using the
- // zero value for both MaxPathLen and MaxPathLenZero.
- MaxPathLen int
- // MaxPathLenZero indicates that BasicConstraintsValid==true
- // and MaxPathLen==0 should be interpreted as an actual
- // maximum path length of zero. Otherwise, that combination is
- // interpreted as MaxPathLen not being set.
- MaxPathLenZero bool
- SubjectKeyId []byte
- AuthorityKeyId []byte
- // RFC 5280, 4.2.2.1 (Authority Information Access)
- OCSPServer []string
- IssuingCertificateURL []string
- // Subject Alternate Name values. (Note that these values may not be valid
- // if invalid values were contained within a parsed certificate. For
- // example, an element of DNSNames may not be a valid DNS domain name.)
- DNSNames []string
- EmailAddresses []string
- IPAddresses []net.IP
- URIs []*url.URL
- // Name constraints
- PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
- PermittedDNSDomains []string
- ExcludedDNSDomains []string
- PermittedIPRanges []*net.IPNet
- ExcludedIPRanges []*net.IPNet
- PermittedEmailAddresses []string
- ExcludedEmailAddresses []string
- PermittedURIDomains []string
- ExcludedURIDomains []string
- // CRL Distribution Points
- CRLDistributionPoints []string
- // PolicyIdentifiers contains asn1.ObjectIdentifiers, the components
- // of which are limited to int32. If a certificate contains a policy which
- // cannot be represented by asn1.ObjectIdentifier, it will not be included in
- // PolicyIdentifiers, but will be present in Policies, which contains all parsed
- // policy OIDs.
- PolicyIdentifiers []asn1.ObjectIdentifier
- // Policies contains all policy identifiers included in the certificate.
- // In Go 1.22, encoding/gob cannot handle and ignores this field.
- Policies []OID
- }
- // ErrUnsupportedAlgorithm results from attempting to perform an operation that
- // involves algorithms that are not currently implemented.
- var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
- // An InsecureAlgorithmError indicates that the [SignatureAlgorithm] used to
- // generate the signature is not secure, and the signature has been rejected.
- //
- // To temporarily restore support for SHA-1 signatures, include the value
- // "x509sha1=1" in the GODEBUG environment variable. Note that this option will
- // be removed in a future release.
- type InsecureAlgorithmError SignatureAlgorithm
- func (e InsecureAlgorithmError) Error() string {
- var override string
- if SignatureAlgorithm(e) == SHA1WithRSA || SignatureAlgorithm(e) == ECDSAWithSHA1 {
- override = " (temporarily override with GODEBUG=x509sha1=1)"
- }
- return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + override
- }
- // ConstraintViolationError results when a requested usage is not permitted by
- // a certificate. For example: checking a signature when the public key isn't a
- // certificate signing key.
- type ConstraintViolationError struct{}
- func (ConstraintViolationError) Error() string {
- return "x509: invalid signature: parent certificate cannot sign this kind of certificate"
- }
- func (c *Certificate) Equal(other *Certificate) bool {
- if c == nil || other == nil {
- return c == other
- }
- return bytes.Equal(c.Raw, other.Raw)
- }
- func (c *Certificate) hasSANExtension() bool {
- return oidInExtensions(oidExtensionSubjectAltName, c.Extensions)
- }
- // CheckSignatureFrom verifies that the signature on c is a valid signature from parent.
- //
- // This is a low-level API that performs very limited checks, and not a full
- // path verifier. Most users should use [Certificate.Verify] instead.
- func (c *Certificate) CheckSignatureFrom(parent *Certificate) error {
- // RFC 5280, 4.2.1.9:
- // "If the basic constraints extension is not present in a version 3
- // certificate, or the extension is present but the cA boolean is not
- // asserted, then the certified public key MUST NOT be used to verify
- // certificate signatures."
- if parent.Version == 3 && !parent.BasicConstraintsValid ||
- parent.BasicConstraintsValid && !parent.IsCA {
- return ConstraintViolationError{}
- }
- if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 {
- return ConstraintViolationError{}
- }
- if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm {
- return ErrUnsupportedAlgorithm
- }
- return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, false)
- }
- // CheckSignature verifies that signature is a valid signature over signed from
- // c's public key.
- //
- // This is a low-level API that performs no validity checks on the certificate.
- //
- // [MD5WithRSA] signatures are rejected, while [SHA1WithRSA] and [ECDSAWithSHA1]
- // signatures are currently accepted.
- func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) error {
- return checkSignature(algo, signed, signature, c.PublicKey, true)
- }
- func (c *Certificate) hasNameConstraints() bool {
- return oidInExtensions(oidExtensionNameConstraints, c.Extensions)
- }
- func (c *Certificate) getSANExtension() []byte {
- for _, e := range c.Extensions {
- if e.Id.Equal(oidExtensionSubjectAltName) {
- return e.Value
- }
- }
- return nil
- }
- func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey any) error {
- return fmt.Errorf("x509: signature algorithm specifies an %s public key, but have public key of type %T", expectedPubKeyAlgo.String(), pubKey)
- }
- var x509sha1 = godebug.New("x509sha1")
- // checkSignature verifies that signature is a valid signature over signed from
- // a crypto.PublicKey.
- func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey crypto.PublicKey, allowSHA1 bool) (err error) {
- var hashType crypto.Hash
- var pubKeyAlgo PublicKeyAlgorithm
- for _, details := range signatureAlgorithmDetails {
- if details.algo == algo {
- hashType = details.hash
- pubKeyAlgo = details.pubKeyAlgo
- break
- }
- }
- switch hashType {
- case crypto.Hash(0):
- if pubKeyAlgo != Ed25519 {
- return ErrUnsupportedAlgorithm
- }
- case crypto.MD5:
- return InsecureAlgorithmError(algo)
- case crypto.SHA1:
- // SHA-1 signatures are mostly disabled. See go.dev/issue/41682.
- if !allowSHA1 {
- if x509sha1.Value() != "1" {
- return InsecureAlgorithmError(algo)
- }
- x509sha1.IncNonDefault()
- }
- fallthrough
- default:
- if !hashType.Available() {
- return ErrUnsupportedAlgorithm
- }
- h := hashType.New()
- h.Write(signed)
- signed = h.Sum(nil)
- }
- switch pub := publicKey.(type) {
- case *rsa.PublicKey:
- if pubKeyAlgo != RSA {
- return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub)
- }
- if algo.isRSAPSS() {
- return rsa.VerifyPSS(pub, hashType, signed, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash})
- } else {
- return rsa.VerifyPKCS1v15(pub, hashType, signed, signature)
- }
- case *ecdsa.PublicKey:
- if pubKeyAlgo != ECDSA {
- return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub)
- }
- if !ecdsa.VerifyASN1(pub, signed, signature) {
- return errors.New("x509: ECDSA verification failure")
- }
- return
- case ed25519.PublicKey:
- if pubKeyAlgo != Ed25519 {
- return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub)
- }
- if !ed25519.Verify(pub, signed, signature) {
- return errors.New("x509: Ed25519 verification failure")
- }
- return
- }
- return ErrUnsupportedAlgorithm
- }
- // CheckCRLSignature checks that the signature in crl is from c.
- //
- // Deprecated: Use [RevocationList.CheckSignatureFrom] instead.
- func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error {
- algo := getSignatureAlgorithmFromAI(crl.SignatureAlgorithm)
- return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
- }
- type UnhandledCriticalExtension struct{}
- func (h UnhandledCriticalExtension) Error() string {
- return "x509: unhandled critical extension"
- }
- type basicConstraints struct {
- IsCA bool `asn1:"optional"`
- MaxPathLen int `asn1:"optional,default:-1"`
- }
- // RFC 5280 4.2.1.4
- type policyInformation struct {
- Policy asn1.ObjectIdentifier
- // policyQualifiers omitted
- }
- const (
- nameTypeEmail = 1
- nameTypeDNS = 2
- nameTypeURI = 6
- nameTypeIP = 7
- )
- // RFC 5280, 4.2.2.1
- type authorityInfoAccess struct {
- Method asn1.ObjectIdentifier
- Location asn1.RawValue
- }
- // RFC 5280, 4.2.1.14
- type distributionPoint struct {
- DistributionPoint distributionPointName `asn1:"optional,tag:0"`
- Reason asn1.BitString `asn1:"optional,tag:1"`
- CRLIssuer asn1.RawValue `asn1:"optional,tag:2"`
- }
- type distributionPointName struct {
- FullName []asn1.RawValue `asn1:"optional,tag:0"`
- RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
- }
- func reverseBitsInAByte(in byte) byte {
- b1 := in>>4 | in<<4
- b2 := b1>>2&0x33 | b1<<2&0xcc
- b3 := b2>>1&0x55 | b2<<1&0xaa
- return b3
- }
- // asn1BitLength returns the bit-length of bitString by considering the
- // most-significant bit in a byte to be the "first" bit. This convention
- // matches ASN.1, but differs from almost everything else.
- func asn1BitLength(bitString []byte) int {
- bitLen := len(bitString) * 8
- for i := range bitString {
- b := bitString[len(bitString)-i-1]
- for bit := uint(0); bit < 8; bit++ {
- if (b>>bit)&1 == 1 {
- return bitLen
- }
- bitLen--
- }
- }
- return 0
- }
- var (
- oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
- oidExtensionKeyUsage = []int{2, 5, 29, 15}
- oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
- oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
- oidExtensionBasicConstraints = []int{2, 5, 29, 19}
- oidExtensionSubjectAltName = []int{2, 5, 29, 17}
- oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
- oidExtensionNameConstraints = []int{2, 5, 29, 30}
- oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
- oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}
- oidExtensionCRLNumber = []int{2, 5, 29, 20}
- oidExtensionReasonCode = []int{2, 5, 29, 21}
- )
- var (
- oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1}
- oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2}
- )
- // oidInExtensions reports whether an extension with the given oid exists in
- // extensions.
- func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool {
- for _, e := range extensions {
- if e.Id.Equal(oid) {
- return true
- }
- }
- return false
- }
- // marshalSANs marshals a list of addresses into a the contents of an X.509
- // SubjectAlternativeName extension.
- func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) (derBytes []byte, err error) {
- var rawValues []asn1.RawValue
- for _, name := range dnsNames {
- if err := isIA5String(name); err != nil {
- return nil, err
- }
- rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeDNS, Class: 2, Bytes: []byte(name)})
- }
- for _, email := range emailAddresses {
- if err := isIA5String(email); err != nil {
- return nil, err
- }
- rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeEmail, Class: 2, Bytes: []byte(email)})
- }
- for _, rawIP := range ipAddresses {
- // If possible, we always want to encode IPv4 addresses in 4 bytes.
- ip := rawIP.To4()
- if ip == nil {
- ip = rawIP
- }
- rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeIP, Class: 2, Bytes: ip})
- }
- for _, uri := range uris {
- uriStr := uri.String()
- if err := isIA5String(uriStr); err != nil {
- return nil, err
- }
- rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeURI, Class: 2, Bytes: []byte(uriStr)})
- }
- return asn1.Marshal(rawValues)
- }
- func isIA5String(s string) error {
- for _, r := range s {
- // Per RFC5280 "IA5String is limited to the set of ASCII characters"
- if r > unicode.MaxASCII {
- return fmt.Errorf("x509: %q cannot be encoded as an IA5String", s)
- }
- }
- return nil
- }
- var usePoliciesField = godebug.New("x509usepolicies")
- func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId []byte, subjectKeyId []byte) (ret []pkix.Extension, err error) {
- ret = make([]pkix.Extension, 10 /* maximum number of elements. */)
- n := 0
- if template.KeyUsage != 0 &&
- !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {
- ret[n], err = marshalKeyUsage(template.KeyUsage)
- if err != nil {
- return nil, err
- }
- n++
- }
- if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) &&
- !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) {
- ret[n], err = marshalExtKeyUsage(template.ExtKeyUsage, template.UnknownExtKeyUsage)
- if err != nil {
- return nil, err
- }
- n++
- }
- if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {
- ret[n], err = marshalBasicConstraints(template.IsCA, template.MaxPathLen, template.MaxPathLenZero)
- if err != nil {
- return nil, err
- }
- n++
- }
- if len(subjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) {
- ret[n].Id = oidExtensionSubjectKeyId
- ret[n].Value, err = asn1.Marshal(subjectKeyId)
- if err != nil {
- return
- }
- n++
- }
- if len(authorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {
- ret[n].Id = oidExtensionAuthorityKeyId
- ret[n].Value, err = asn1.Marshal(authKeyId{authorityKeyId})
- if err != nil {
- return
- }
- n++
- }
- if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) &&
- !oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) {
- ret[n].Id = oidExtensionAuthorityInfoAccess
- var aiaValues []authorityInfoAccess
- for _, name := range template.OCSPServer {
- aiaValues = append(aiaValues, authorityInfoAccess{
- Method: oidAuthorityInfoAccessOcsp,
- Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
- })
- }
- for _, name := range template.IssuingCertificateURL {
- aiaValues = append(aiaValues, authorityInfoAccess{
- Method: oidAuthorityInfoAccessIssuers,
- Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
- })
- }
- ret[n].Value, err = asn1.Marshal(aiaValues)
- if err != nil {
- return
- }
- n++
- }
- if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) &&
- !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
- ret[n].Id = oidExtensionSubjectAltName
- // From RFC 5280, Section 4.2.1.6:
- // “If the subject field contains an empty sequence ... then
- // subjectAltName extension ... is marked as critical”
- ret[n].Critical = subjectIsEmpty
- ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs)
- if err != nil {
- return
- }
- n++
- }
- usePolicies := usePoliciesField.Value() == "1"
- if ((!usePolicies && len(template.PolicyIdentifiers) > 0) || (usePolicies && len(template.Policies) > 0)) &&
- !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {
- ret[n], err = marshalCertificatePolicies(template.Policies, template.PolicyIdentifiers)
- if err != nil {
- return nil, err
- }
- n++
- }
- if (len(template.PermittedDNSDomains) > 0 || len(template.ExcludedDNSDomains) > 0 ||
- len(template.PermittedIPRanges) > 0 || len(template.ExcludedIPRanges) > 0 ||
- len(template.PermittedEmailAddresses) > 0 || len(template.ExcludedEmailAddresses) > 0 ||
- len(template.PermittedURIDomains) > 0 || len(template.ExcludedURIDomains) > 0) &&
- !oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) {
- ret[n].Id = oidExtensionNameConstraints
- ret[n].Critical = template.PermittedDNSDomainsCritical
- ipAndMask := func(ipNet *net.IPNet) []byte {
- maskedIP := ipNet.IP.Mask(ipNet.Mask)
- ipAndMask := make([]byte, 0, len(maskedIP)+len(ipNet.Mask))
- ipAndMask = append(ipAndMask, maskedIP...)
- ipAndMask = append(ipAndMask, ipNet.Mask...)
- return ipAndMask
- }
- serialiseConstraints := func(dns []string, ips []*net.IPNet, emails []string, uriDomains []string) (der []byte, err error) {
- var b cryptobyte.Builder
- for _, name := range dns {
- if err = isIA5String(name); err != nil {
- return nil, err
- }
- b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
- b.AddASN1(cryptobyte_asn1.Tag(2).ContextSpecific(), func(b *cryptobyte.Builder) {
- b.AddBytes([]byte(name))
- })
- })
- }
- for _, ipNet := range ips {
- b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
- b.AddASN1(cryptobyte_asn1.Tag(7).ContextSpecific(), func(b *cryptobyte.Builder) {
- b.AddBytes(ipAndMask(ipNet))
- })
- })
- }
- for _, email := range emails {
- if err = isIA5String(email); err != nil {
- return nil, err
- }
- b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
- b.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific(), func(b *cryptobyte.Builder) {
- b.AddBytes([]byte(email))
- })
- })
- }
- for _, uriDomain := range uriDomains {
- if err = isIA5String(uriDomain); err != nil {
- return nil, err
- }
- b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
- b.AddASN1(cryptobyte_asn1.Tag(6).ContextSpecific(), func(b *cryptobyte.Builder) {
- b.AddBytes([]byte(uriDomain))
- })
- })
- }
- return b.Bytes()
- }
- permitted, err := serialiseConstraints(template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains)
- if err != nil {
- return nil, err
- }
- excluded, err := serialiseConstraints(template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains)
- if err != nil {
- return nil, err
- }
- var b cryptobyte.Builder
- b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
- if len(permitted) > 0 {
- b.AddASN1(cryptobyte_asn1.Tag(0).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) {
- b.AddBytes(permitted)
- })
- }
- if len(excluded) > 0 {
- b.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) {
- b.AddBytes(excluded)
- })
- }
- })
- ret[n].Value, err = b.Bytes()
- if err != nil {
- return nil, err
- }
- n++
- }
- if len(template.CRLDistributionPoints) > 0 &&
- !oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) {
- ret[n].Id = oidExtensionCRLDistributionPoints
- var crlDp []distributionPoint
- for _, name := range template.CRLDistributionPoints {
- dp := distributionPoint{
- DistributionPoint: distributionPointName{
- FullName: []asn1.RawValue{
- {Tag: 6, Class: 2, Bytes: []byte(name)},
- },
- },
- }
- crlDp = append(crlDp, dp)
- }
- ret[n].Value, err = asn1.Marshal(crlDp)
- if err != nil {
- return
- }
- n++
- }
- // Adding another extension here? Remember to update the maximum number
- // of elements in the make() at the top of the function and the list of
- // template fields used in CreateCertificate documentation.
- return append(ret[:n], template.ExtraExtensions...), nil
- }
- func marshalKeyUsage(ku KeyUsage) (pkix.Extension, error) {
- ext := pkix.Extension{Id: oidExtensionKeyUsage, Critical: true}
- var a [2]byte
- a[0] = reverseBitsInAByte(byte(ku))
- a[1] = reverseBitsInAByte(byte(ku >> 8))
- l := 1
- if a[1] != 0 {
- l = 2
- }
- bitString := a[:l]
- var err error
- ext.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)})
- return ext, err
- }
- func marshalExtKeyUsage(extUsages []ExtKeyUsage, unknownUsages []asn1.ObjectIdentifier) (pkix.Extension, error) {
- ext := pkix.Extension{Id: oidExtensionExtendedKeyUsage}
- oids := make([]asn1.ObjectIdentifier, len(extUsages)+len(unknownUsages))
- for i, u := range extUsages {
- if oid, ok := oidFromExtKeyUsage(u); ok {
- oids[i] = oid
- } else {
- return ext, errors.New("x509: unknown extended key usage")
- }
- }
- copy(oids[len(extUsages):], unknownUsages)
- var err error
- ext.Value, err = asn1.Marshal(oids)
- return ext, err
- }
- func marshalBasicConstraints(isCA bool, maxPathLen int, maxPathLenZero bool) (pkix.Extension, error) {
- ext := pkix.Extension{Id: oidExtensionBasicConstraints, Critical: true}
- // Leaving MaxPathLen as zero indicates that no maximum path
- // length is desired, unless MaxPathLenZero is set. A value of
- // -1 causes encoding/asn1 to omit the value as desired.
- if maxPathLen == 0 && !maxPathLenZero {
- maxPathLen = -1
- }
- var err error
- ext.Value, err = asn1.Marshal(basicConstraints{isCA, maxPathLen})
- return ext, err
- }
- func marshalCertificatePolicies(policies []OID, policyIdentifiers []asn1.ObjectIdentifier) (pkix.Extension, error) {
- ext := pkix.Extension{Id: oidExtensionCertificatePolicies}
- b := cryptobyte.NewBuilder(make([]byte, 0, 128))
- b.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) {
- if usePoliciesField.Value() == "1" {
- usePoliciesField.IncNonDefault()
- for _, v := range policies {
- child.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) {
- child.AddASN1(cryptobyte_asn1.OBJECT_IDENTIFIER, func(child *cryptobyte.Builder) {
- if len(v.der) == 0 {
- child.SetError(errors.New("invalid policy object identifier"))
- return
- }
- child.AddBytes(v.der)
- })
- })
- }
- } else {
- for _, v := range policyIdentifiers {
- child.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) {
- child.AddASN1ObjectIdentifier(v)
- })
- }
- }
- })
- var err error
- ext.Value, err = b.Bytes()
- return ext, err
- }
- func buildCSRExtensions(template *CertificateRequest) ([]pkix.Extension, error) {
- var ret []pkix.Extension
- if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) &&
- !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
- sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs)
- if err != nil {
- return nil, err
- }
- ret = append(ret, pkix.Extension{
- Id: oidExtensionSubjectAltName,
- Value: sanBytes,
- })
- }
- return append(ret, template.ExtraExtensions...), nil
- }
- func subjectBytes(cert *Certificate) ([]byte, error) {
- if len(cert.RawSubject) > 0 {
- return cert.RawSubject, nil
- }
- return asn1.Marshal(cert.Subject.ToRDNSequence())
- }
- // signingParamsForPublicKey returns the parameters to use for signing with
- // priv. If requestedSigAlgo is not zero then it overrides the default
- // signature algorithm.
- func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
- var pubType PublicKeyAlgorithm
- switch pub := pub.(type) {
- case *rsa.PublicKey:
- pubType = RSA
- hashFunc = crypto.SHA256
- sigAlgo.Algorithm = oidSignatureSHA256WithRSA
- sigAlgo.Parameters = asn1.NullRawValue
- case *ecdsa.PublicKey:
- pubType = ECDSA
- switch pub.Curve {
- case elliptic.P224(), elliptic.P256():
- hashFunc = crypto.SHA256
- sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
- case elliptic.P384():
- hashFunc = crypto.SHA384
- sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
- case elliptic.P521():
- hashFunc = crypto.SHA512
- sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
- default:
- err = errors.New("x509: unknown elliptic curve")
- }
- case ed25519.PublicKey:
- pubType = Ed25519
- sigAlgo.Algorithm = oidSignatureEd25519
- default:
- err = errors.New("x509: only RSA, ECDSA and Ed25519 keys supported")
- }
- if err != nil {
- return
- }
- if requestedSigAlgo == 0 {
- return
- }
- found := false
- for _, details := range signatureAlgorithmDetails {
- if details.algo == requestedSigAlgo {
- if details.pubKeyAlgo != pubType {
- err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
- return
- }
- sigAlgo.Algorithm, hashFunc = details.oid, details.hash
- if hashFunc == 0 && pubType != Ed25519 {
- err = errors.New("x509: cannot sign with hash function requested")
- return
- }
- if hashFunc == crypto.MD5 {
- err = errors.New("x509: signing with MD5 is not supported")
- return
- }
- if requestedSigAlgo.isRSAPSS() {
- sigAlgo.Parameters = hashToPSSParameters[hashFunc]
- }
- found = true
- break
- }
- }
- if !found {
- err = errors.New("x509: unknown SignatureAlgorithm")
- }
- return
- }
- // emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is
- // just an empty SEQUENCE.
- var emptyASN1Subject = []byte{0x30, 0}
- // CreateCertificate creates a new X.509 v3 certificate based on a template.
- // The following members of template are currently used:
- //
- // - AuthorityKeyId
- // - BasicConstraintsValid
- // - CRLDistributionPoints
- // - DNSNames
- // - EmailAddresses
- // - ExcludedDNSDomains
- // - ExcludedEmailAddresses
- // - ExcludedIPRanges
- // - ExcludedURIDomains
- // - ExtKeyUsage
- // - ExtraExtensions
- // - IPAddresses
- // - IsCA
- // - IssuingCertificateURL
- // - KeyUsage
- // - MaxPathLen
- // - MaxPathLenZero
- // - NotAfter
- // - NotBefore
- // - OCSPServer
- // - PermittedDNSDomains
- // - PermittedDNSDomainsCritical
- // - PermittedEmailAddresses
- // - PermittedIPRanges
- // - PermittedURIDomains
- // - PolicyIdentifiers (see note below)
- // - Policies (see note below)
- // - SerialNumber
- // - SignatureAlgorithm
- // - Subject
- // - SubjectKeyId
- // - URIs
- // - UnknownExtKeyUsage
- //
- // The certificate is signed by parent. If parent is equal to template then the
- // certificate is self-signed. The parameter pub is the public key of the
- // certificate to be generated and priv is the private key of the signer.
- //
- // The returned slice is the certificate in DER encoding.
- //
- // The currently supported key types are *rsa.PublicKey, *ecdsa.PublicKey and
- // ed25519.PublicKey. pub must be a supported key type, and priv must be a
- // crypto.Signer with a supported public key.
- //
- // The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any,
- // unless the resulting certificate is self-signed. Otherwise the value from
- // template will be used.
- //
- // If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId
- // will be generated from the hash of the public key.
- //
- // The PolicyIdentifier and Policies fields are both used to marshal certificate
- // policy OIDs. By default, only the PolicyIdentifier is marshaled, but if the
- // GODEBUG setting "x509usepolicies" has the value "1", the Policies field will
- // be marshalled instead of the PolicyIdentifier field. The Policies field can
- // be used to marshal policy OIDs which have components that are larger than 31
- // bits.
- func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv any) ([]byte, error) {
- key, ok := priv.(crypto.Signer)
- if !ok {
- return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
- }
- if template.SerialNumber == nil {
- return nil, errors.New("x509: no SerialNumber given")
- }
- // RFC 5280 Section 4.1.2.2: serial number must positive
- //
- // We _should_ also restrict serials to <= 20 octets, but it turns out a lot of people
- // get this wrong, in part because the encoding can itself alter the length of the
- // serial. For now we accept these non-conformant serials.
- if template.SerialNumber.Sign() == -1 {
- return nil, errors.New("x509: serial number must be positive")
- }
- if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) {
- return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen")
- }
- hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
- if err != nil {
- return nil, err
- }
- publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub)
- if err != nil {
- return nil, err
- }
- if getPublicKeyAlgorithmFromOID(publicKeyAlgorithm.Algorithm) == UnknownPublicKeyAlgorithm {
- return nil, fmt.Errorf("x509: unsupported public key type: %T", pub)
- }
- asn1Issuer, err := subjectBytes(parent)
- if err != nil {
- return nil, err
- }
- asn1Subject, err := subjectBytes(template)
- if err != nil {
- return nil, err
- }
- authorityKeyId := template.AuthorityKeyId
- if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 {
- authorityKeyId = parent.SubjectKeyId
- }
- subjectKeyId := template.SubjectKeyId
- if len(subjectKeyId) == 0 && template.IsCA {
- // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2:
- // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
- // value of the BIT STRING subjectPublicKey (excluding the tag,
- // length, and number of unused bits).
- h := sha1.Sum(publicKeyBytes)
- subjectKeyId = h[:]
- }
- // Check that the signer's public key matches the private key, if available.
- type privateKey interface {
- Equal(crypto.PublicKey) bool
- }
- if privPub, ok := key.Public().(privateKey); !ok {
- return nil, errors.New("x509: internal error: supported public key does not implement Equal")
- } else if parent.PublicKey != nil && !privPub.Equal(parent.PublicKey) {
- return nil, errors.New("x509: provided PrivateKey doesn't match parent's PublicKey")
- }
- extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId)
- if err != nil {
- return nil, err
- }
- encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
- c := tbsCertificate{
- Version: 2,
- SerialNumber: template.SerialNumber,
- SignatureAlgorithm: signatureAlgorithm,
- Issuer: asn1.RawValue{FullBytes: asn1Issuer},
- Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
- Subject: asn1.RawValue{FullBytes: asn1Subject},
- PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
- Extensions: extensions,
- }
- tbsCertContents, err := asn1.Marshal(c)
- if err != nil {
- return nil, err
- }
- c.Raw = tbsCertContents
- signed := tbsCertContents
- if hashFunc != 0 {
- h := hashFunc.New()
- h.Write(signed)
- signed = h.Sum(nil)
- }
- var signerOpts crypto.SignerOpts = hashFunc
- if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() {
- signerOpts = &rsa.PSSOptions{
- SaltLength: rsa.PSSSaltLengthEqualsHash,
- Hash: hashFunc,
- }
- }
- var signature []byte
- signature, err = key.Sign(rand, signed, signerOpts)
- if err != nil {
- return nil, err
- }
- signedCert, err := asn1.Marshal(certificate{
- c,
- signatureAlgorithm,
- asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
- })
- if err != nil {
- return nil, err
- }
- // Check the signature to ensure the crypto.Signer behaved correctly.
- if err := checkSignature(getSignatureAlgorithmFromAI(signatureAlgorithm), c.Raw, signature, key.Public(), true); err != nil {
- return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err)
- }
- return signedCert, nil
- }
- // pemCRLPrefix is the magic string that indicates that we have a PEM encoded
- // CRL.
- var pemCRLPrefix = []byte("-----BEGIN X509 CRL")
- // pemType is the type of a PEM encoded CRL.
- var pemType = "X509 CRL"
- // ParseCRL parses a CRL from the given bytes. It's often the case that PEM
- // encoded CRLs will appear where they should be DER encoded, so this function
- // will transparently handle PEM encoding as long as there isn't any leading
- // garbage.
- //
- // Deprecated: Use [ParseRevocationList] instead.
- func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) {
- if bytes.HasPrefix(crlBytes, pemCRLPrefix) {
- block, _ := pem.Decode(crlBytes)
- if block != nil && block.Type == pemType {
- crlBytes = block.Bytes
- }
- }
- return ParseDERCRL(crlBytes)
- }
- // ParseDERCRL parses a DER encoded CRL from the given bytes.
- //
- // Deprecated: Use [ParseRevocationList] instead.
- func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) {
- certList := new(pkix.CertificateList)
- if rest, err := asn1.Unmarshal(derBytes, certList); err != nil {
- return nil, err
- } else if len(rest) != 0 {
- return nil, errors.New("x509: trailing data after CRL")
- }
- return certList, nil
- }
- // CreateCRL returns a DER encoded CRL, signed by this Certificate, that
- // contains the given list of revoked certificates.
- //
- // Deprecated: this method does not generate an RFC 5280 conformant X.509 v2 CRL.
- // To generate a standards compliant CRL, use [CreateRevocationList] instead.
- func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
- key, ok := priv.(crypto.Signer)
- if !ok {
- return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
- }
- hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0)
- if err != nil {
- return nil, err
- }
- // Force revocation times to UTC per RFC 5280.
- revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts))
- for i, rc := range revokedCerts {
- rc.RevocationTime = rc.RevocationTime.UTC()
- revokedCertsUTC[i] = rc
- }
- tbsCertList := pkix.TBSCertificateList{
- Version: 1,
- Signature: signatureAlgorithm,
- Issuer: c.Subject.ToRDNSequence(),
- ThisUpdate: now.UTC(),
- NextUpdate: expiry.UTC(),
- RevokedCertificates: revokedCertsUTC,
- }
- // Authority Key Id
- if len(c.SubjectKeyId) > 0 {
- var aki pkix.Extension
- aki.Id = oidExtensionAuthorityKeyId
- aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId})
- if err != nil {
- return
- }
- tbsCertList.Extensions = append(tbsCertList.Extensions, aki)
- }
- tbsCertListContents, err := asn1.Marshal(tbsCertList)
- if err != nil {
- return
- }
- signed := tbsCertListContents
- if hashFunc != 0 {
- h := hashFunc.New()
- h.Write(signed)
- signed = h.Sum(nil)
- }
- var signature []byte
- signature, err = key.Sign(rand, signed, hashFunc)
- if err != nil {
- return
- }
- return asn1.Marshal(pkix.CertificateList{
- TBSCertList: tbsCertList,
- SignatureAlgorithm: signatureAlgorithm,
- SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
- })
- }
- // CertificateRequest represents a PKCS #10, certificate signature request.
- type CertificateRequest struct {
- Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature).
- RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content.
- RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
- RawSubject []byte // DER encoded Subject.
- Version int
- Signature []byte
- SignatureAlgorithm SignatureAlgorithm
- PublicKeyAlgorithm PublicKeyAlgorithm
- PublicKey any
- Subject pkix.Name
- // Attributes contains the CSR attributes that can parse as
- // pkix.AttributeTypeAndValueSET.
- //
- // Deprecated: Use Extensions and ExtraExtensions instead for parsing and
- // generating the requestedExtensions attribute.
- Attributes []pkix.AttributeTypeAndValueSET
- // Extensions contains all requested extensions, in raw form. When parsing
- // CSRs, this can be used to extract extensions that are not parsed by this
- // package.
- Extensions []pkix.Extension
- // ExtraExtensions contains extensions to be copied, raw, into any CSR
- // marshaled by CreateCertificateRequest. Values override any extensions
- // that would otherwise be produced based on the other fields but are
- // overridden by any extensions specified in Attributes.
- //
- // The ExtraExtensions field is not populated by ParseCertificateRequest,
- // see Extensions instead.
- ExtraExtensions []pkix.Extension
- // Subject Alternate Name values.
- DNSNames []string
- EmailAddresses []string
- IPAddresses []net.IP
- URIs []*url.URL
- }
- // These structures reflect the ASN.1 structure of X.509 certificate
- // signature requests (see RFC 2986):
- type tbsCertificateRequest struct {
- Raw asn1.RawContent
- Version int
- Subject asn1.RawValue
- PublicKey publicKeyInfo
- RawAttributes []asn1.RawValue `asn1:"tag:0"`
- }
- type certificateRequest struct {
- Raw asn1.RawContent
- TBSCSR tbsCertificateRequest
- SignatureAlgorithm pkix.AlgorithmIdentifier
- SignatureValue asn1.BitString
- }
- // oidExtensionRequest is a PKCS #9 OBJECT IDENTIFIER that indicates requested
- // extensions in a CSR.
- var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}
- // newRawAttributes converts AttributeTypeAndValueSETs from a template
- // CertificateRequest's Attributes into tbsCertificateRequest RawAttributes.
- func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) {
- var rawAttributes []asn1.RawValue
- b, err := asn1.Marshal(attributes)
- if err != nil {
- return nil, err
- }
- rest, err := asn1.Unmarshal(b, &rawAttributes)
- if err != nil {
- return nil, err
- }
- if len(rest) != 0 {
- return nil, errors.New("x509: failed to unmarshal raw CSR Attributes")
- }
- return rawAttributes, nil
- }
- // parseRawAttributes Unmarshals RawAttributes into AttributeTypeAndValueSETs.
- func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET {
- var attributes []pkix.AttributeTypeAndValueSET
- for _, rawAttr := range rawAttributes {
- var attr pkix.AttributeTypeAndValueSET
- rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr)
- // Ignore attributes that don't parse into pkix.AttributeTypeAndValueSET
- // (i.e.: challengePassword or unstructuredName).
- if err == nil && len(rest) == 0 {
- attributes = append(attributes, attr)
- }
- }
- return attributes
- }
- // parseCSRExtensions parses the attributes from a CSR and extracts any
- // requested extensions.
- func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) {
- // pkcs10Attribute reflects the Attribute structure from RFC 2986, Section 4.1.
- type pkcs10Attribute struct {
- Id asn1.ObjectIdentifier
- Values []asn1.RawValue `asn1:"set"`
- }
- var ret []pkix.Extension
- requestedExts := make(map[string]bool)
- for _, rawAttr := range rawAttributes {
- var attr pkcs10Attribute
- if rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 {
- // Ignore attributes that don't parse.
- continue
- }
- if !attr.Id.Equal(oidExtensionRequest) {
- continue
- }
- var extensions []pkix.Extension
- if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil {
- return nil, err
- }
- for _, ext := range extensions {
- oidStr := ext.Id.String()
- if requestedExts[oidStr] {
- return nil, errors.New("x509: certificate request contains duplicate requested extensions")
- }
- requestedExts[oidStr] = true
- }
- ret = append(ret, extensions...)
- }
- return ret, nil
- }
- // CreateCertificateRequest creates a new certificate request based on a
- // template. The following members of template are used:
- //
- // - SignatureAlgorithm
- // - Subject
- // - DNSNames
- // - EmailAddresses
- // - IPAddresses
- // - URIs
- // - ExtraExtensions
- // - Attributes (deprecated)
- //
- // priv is the private key to sign the CSR with, and the corresponding public
- // key will be included in the CSR. It must implement crypto.Signer and its
- // Public() method must return a *rsa.PublicKey or a *ecdsa.PublicKey or a
- // ed25519.PublicKey. (A *rsa.PrivateKey, *ecdsa.PrivateKey or
- // ed25519.PrivateKey satisfies this.)
- //
- // The returned slice is the certificate request in DER encoding.
- func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv any) (csr []byte, err error) {
- key, ok := priv.(crypto.Signer)
- if !ok {
- return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
- }
- var hashFunc crypto.Hash
- var sigAlgo pkix.AlgorithmIdentifier
- hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
- if err != nil {
- return nil, err
- }
- var publicKeyBytes []byte
- var publicKeyAlgorithm pkix.AlgorithmIdentifier
- publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public())
- if err != nil {
- return nil, err
- }
- extensions, err := buildCSRExtensions(template)
- if err != nil {
- return nil, err
- }
- // Make a copy of template.Attributes because we may alter it below.
- attributes := make([]pkix.AttributeTypeAndValueSET, 0, len(template.Attributes))
- for _, attr := range template.Attributes {
- values := make([][]pkix.AttributeTypeAndValue, len(attr.Value))
- copy(values, attr.Value)
- attributes = append(attributes, pkix.AttributeTypeAndValueSET{
- Type: attr.Type,
- Value: values,
- })
- }
- extensionsAppended := false
- if len(extensions) > 0 {
- // Append the extensions to an existing attribute if possible.
- for _, atvSet := range attributes {
- if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 {
- continue
- }
- // specifiedExtensions contains all the extensions that we
- // found specified via template.Attributes.
- specifiedExtensions := make(map[string]bool)
- for _, atvs := range atvSet.Value {
- for _, atv := range atvs {
- specifiedExtensions[atv.Type.String()] = true
- }
- }
- newValue := make([]pkix.AttributeTypeAndValue, 0, len(atvSet.Value[0])+len(extensions))
- newValue = append(newValue, atvSet.Value[0]...)
- for _, e := range extensions {
- if specifiedExtensions[e.Id.String()] {
- // Attributes already contained a value for
- // this extension and it takes priority.
- continue
- }
- newValue = append(newValue, pkix.AttributeTypeAndValue{
- // There is no place for the critical
- // flag in an AttributeTypeAndValue.
- Type: e.Id,
- Value: e.Value,
- })
- }
- atvSet.Value[0] = newValue
- extensionsAppended = true
- break
- }
- }
- rawAttributes, err := newRawAttributes(attributes)
- if err != nil {
- return
- }
- // If not included in attributes, add a new attribute for the
- // extensions.
- if len(extensions) > 0 && !extensionsAppended {
- attr := struct {
- Type asn1.ObjectIdentifier
- Value [][]pkix.Extension `asn1:"set"`
- }{
- Type: oidExtensionRequest,
- Value: [][]pkix.Extension{extensions},
- }
- b, err := asn1.Marshal(attr)
- if err != nil {
- return nil, errors.New("x509: failed to serialise extensions attribute: " + err.Error())
- }
- var rawValue asn1.RawValue
- if _, err := asn1.Unmarshal(b, &rawValue); err != nil {
- return nil, err
- }
- rawAttributes = append(rawAttributes, rawValue)
- }
- asn1Subject := template.RawSubject
- if len(asn1Subject) == 0 {
- asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence())
- if err != nil {
- return nil, err
- }
- }
- tbsCSR := tbsCertificateRequest{
- Version: 0, // PKCS #10, RFC 2986
- Subject: asn1.RawValue{FullBytes: asn1Subject},
- PublicKey: publicKeyInfo{
- Algorithm: publicKeyAlgorithm,
- PublicKey: asn1.BitString{
- Bytes: publicKeyBytes,
- BitLength: len(publicKeyBytes) * 8,
- },
- },
- RawAttributes: rawAttributes,
- }
- tbsCSRContents, err := asn1.Marshal(tbsCSR)
- if err != nil {
- return
- }
- tbsCSR.Raw = tbsCSRContents
- signed := tbsCSRContents
- if hashFunc != 0 {
- h := hashFunc.New()
- h.Write(signed)
- signed = h.Sum(nil)
- }
- var signature []byte
- signature, err = key.Sign(rand, signed, hashFunc)
- if err != nil {
- return
- }
- return asn1.Marshal(certificateRequest{
- TBSCSR: tbsCSR,
- SignatureAlgorithm: sigAlgo,
- SignatureValue: asn1.BitString{
- Bytes: signature,
- BitLength: len(signature) * 8,
- },
- })
- }
- // ParseCertificateRequest parses a single certificate request from the
- // given ASN.1 DER data.
- func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) {
- var csr certificateRequest
- rest, err := asn1.Unmarshal(asn1Data, &csr)
- if err != nil {
- return nil, err
- } else if len(rest) != 0 {
- return nil, asn1.SyntaxError{Msg: "trailing data"}
- }
- return parseCertificateRequest(&csr)
- }
- func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) {
- out := &CertificateRequest{
- Raw: in.Raw,
- RawTBSCertificateRequest: in.TBSCSR.Raw,
- RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw,
- RawSubject: in.TBSCSR.Subject.FullBytes,
- Signature: in.SignatureValue.RightAlign(),
- SignatureAlgorithm: getSignatureAlgorithmFromAI(in.SignatureAlgorithm),
- PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm),
- Version: in.TBSCSR.Version,
- Attributes: parseRawAttributes(in.TBSCSR.RawAttributes),
- }
- var err error
- if out.PublicKeyAlgorithm != UnknownPublicKeyAlgorithm {
- out.PublicKey, err = parsePublicKey(&in.TBSCSR.PublicKey)
- if err != nil {
- return nil, err
- }
- }
- var subject pkix.RDNSequence
- if rest, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil {
- return nil, err
- } else if len(rest) != 0 {
- return nil, errors.New("x509: trailing data after X.509 Subject")
- }
- out.Subject.FillFromRDNSequence(&subject)
- if out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil {
- return nil, err
- }
- for _, extension := range out.Extensions {
- switch {
- case extension.Id.Equal(oidExtensionSubjectAltName):
- out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(extension.Value)
- if err != nil {
- return nil, err
- }
- }
- }
- return out, nil
- }
- // CheckSignature reports whether the signature on c is valid.
- func (c *CertificateRequest) CheckSignature() error {
- return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey, true)
- }
- // RevocationListEntry represents an entry in the revokedCertificates
- // sequence of a CRL.
- type RevocationListEntry struct {
- // Raw contains the raw bytes of the revokedCertificates entry. It is set when
- // parsing a CRL; it is ignored when generating a CRL.
- Raw []byte
- // SerialNumber represents the serial number of a revoked certificate. It is
- // both used when creating a CRL and populated when parsing a CRL. It must not
- // be nil.
- SerialNumber *big.Int
- // RevocationTime represents the time at which the certificate was revoked. It
- // is both used when creating a CRL and populated when parsing a CRL. It must
- // not be the zero time.
- RevocationTime time.Time
- // ReasonCode represents the reason for revocation, using the integer enum
- // values specified in RFC 5280 Section 5.3.1. When creating a CRL, the zero
- // value will result in the reasonCode extension being omitted. When parsing a
- // CRL, the zero value may represent either the reasonCode extension being
- // absent (which implies the default revocation reason of 0/Unspecified), or
- // it may represent the reasonCode extension being present and explicitly
- // containing a value of 0/Unspecified (which should not happen according to
- // the DER encoding rules, but can and does happen anyway).
- ReasonCode int
- // Extensions contains raw X.509 extensions. When parsing CRL entries,
- // this can be used to extract non-critical extensions that are not
- // parsed by this package. When marshaling CRL entries, the Extensions
- // field is ignored, see ExtraExtensions.
- Extensions []pkix.Extension
- // ExtraExtensions contains extensions to be copied, raw, into any
- // marshaled CRL entries. Values override any extensions that would
- // otherwise be produced based on the other fields. The ExtraExtensions
- // field is not populated when parsing CRL entries, see Extensions.
- ExtraExtensions []pkix.Extension
- }
- // RevocationList represents a [Certificate] Revocation List (CRL) as specified
- // by RFC 5280.
- type RevocationList struct {
- // Raw contains the complete ASN.1 DER content of the CRL (tbsCertList,
- // signatureAlgorithm, and signatureValue.)
- Raw []byte
- // RawTBSRevocationList contains just the tbsCertList portion of the ASN.1
- // DER.
- RawTBSRevocationList []byte
- // RawIssuer contains the DER encoded Issuer.
- RawIssuer []byte
- // Issuer contains the DN of the issuing certificate.
- Issuer pkix.Name
- // AuthorityKeyId is used to identify the public key associated with the
- // issuing certificate. It is populated from the authorityKeyIdentifier
- // extension when parsing a CRL. It is ignored when creating a CRL; the
- // extension is populated from the issuing certificate itself.
- AuthorityKeyId []byte
- Signature []byte
- // SignatureAlgorithm is used to determine the signature algorithm to be
- // used when signing the CRL. If 0 the default algorithm for the signing
- // key will be used.
- SignatureAlgorithm SignatureAlgorithm
- // RevokedCertificateEntries represents the revokedCertificates sequence in
- // the CRL. It is used when creating a CRL and also populated when parsing a
- // CRL. When creating a CRL, it may be empty or nil, in which case the
- // revokedCertificates ASN.1 sequence will be omitted from the CRL entirely.
- RevokedCertificateEntries []RevocationListEntry
- // RevokedCertificates is used to populate the revokedCertificates
- // sequence in the CRL if RevokedCertificateEntries is empty. It may be empty
- // or nil, in which case an empty CRL will be created.
- //
- // Deprecated: Use RevokedCertificateEntries instead.
- RevokedCertificates []pkix.RevokedCertificate
- // Number is used to populate the X.509 v2 cRLNumber extension in the CRL,
- // which should be a monotonically increasing sequence number for a given
- // CRL scope and CRL issuer. It is also populated from the cRLNumber
- // extension when parsing a CRL.
- Number *big.Int
- // ThisUpdate is used to populate the thisUpdate field in the CRL, which
- // indicates the issuance date of the CRL.
- ThisUpdate time.Time
- // NextUpdate is used to populate the nextUpdate field in the CRL, which
- // indicates the date by which the next CRL will be issued. NextUpdate
- // must be greater than ThisUpdate.
- NextUpdate time.Time
- // Extensions contains raw X.509 extensions. When creating a CRL,
- // the Extensions field is ignored, see ExtraExtensions.
- Extensions []pkix.Extension
- // ExtraExtensions contains any additional extensions to add directly to
- // the CRL.
- ExtraExtensions []pkix.Extension
- }
- // These structures reflect the ASN.1 structure of X.509 CRLs better than
- // the existing crypto/x509/pkix variants do. These mirror the existing
- // certificate structs in this file.
- //
- // Notably, we include issuer as an asn1.RawValue, mirroring the behavior of
- // tbsCertificate and allowing raw (unparsed) subjects to be passed cleanly.
- type certificateList struct {
- TBSCertList tbsCertificateList
- SignatureAlgorithm pkix.AlgorithmIdentifier
- SignatureValue asn1.BitString
- }
- type tbsCertificateList struct {
- Raw asn1.RawContent
- Version int `asn1:"optional,default:0"`
- Signature pkix.AlgorithmIdentifier
- Issuer asn1.RawValue
- ThisUpdate time.Time
- NextUpdate time.Time `asn1:"optional"`
- RevokedCertificates []pkix.RevokedCertificate `asn1:"optional"`
- Extensions []pkix.Extension `asn1:"tag:0,optional,explicit"`
- }
- // CreateRevocationList creates a new X.509 v2 [Certificate] Revocation List,
- // according to RFC 5280, based on template.
- //
- // The CRL is signed by priv which should be the private key associated with
- // the public key in the issuer certificate.
- //
- // The issuer may not be nil, and the crlSign bit must be set in [KeyUsage] in
- // order to use it as a CRL issuer.
- //
- // The issuer distinguished name CRL field and authority key identifier
- // extension are populated using the issuer certificate. issuer must have
- // SubjectKeyId set.
- func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Certificate, priv crypto.Signer) ([]byte, error) {
- if template == nil {
- return nil, errors.New("x509: template can not be nil")
- }
- if issuer == nil {
- return nil, errors.New("x509: issuer can not be nil")
- }
- if (issuer.KeyUsage & KeyUsageCRLSign) == 0 {
- return nil, errors.New("x509: issuer must have the crlSign key usage bit set")
- }
- if len(issuer.SubjectKeyId) == 0 {
- return nil, errors.New("x509: issuer certificate doesn't contain a subject key identifier")
- }
- if template.NextUpdate.Before(template.ThisUpdate) {
- return nil, errors.New("x509: template.ThisUpdate is after template.NextUpdate")
- }
- if template.Number == nil {
- return nil, errors.New("x509: template contains nil Number field")
- }
- hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
- if err != nil {
- return nil, err
- }
- var revokedCerts []pkix.RevokedCertificate
- // Only process the deprecated RevokedCertificates field if it is populated
- // and the new RevokedCertificateEntries field is not populated.
- if len(template.RevokedCertificates) > 0 && len(template.RevokedCertificateEntries) == 0 {
- // Force revocation times to UTC per RFC 5280.
- revokedCerts = make([]pkix.RevokedCertificate, len(template.RevokedCertificates))
- for i, rc := range template.RevokedCertificates {
- rc.RevocationTime = rc.RevocationTime.UTC()
- revokedCerts[i] = rc
- }
- } else {
- // Convert the ReasonCode field to a proper extension, and force revocation
- // times to UTC per RFC 5280.
- revokedCerts = make([]pkix.RevokedCertificate, len(template.RevokedCertificateEntries))
- for i, rce := range template.RevokedCertificateEntries {
- if rce.SerialNumber == nil {
- return nil, errors.New("x509: template contains entry with nil SerialNumber field")
- }
- if rce.RevocationTime.IsZero() {
- return nil, errors.New("x509: template contains entry with zero RevocationTime field")
- }
- rc := pkix.RevokedCertificate{
- SerialNumber: rce.SerialNumber,
- RevocationTime: rce.RevocationTime.UTC(),
- }
- // Copy over any extra extensions, except for a Reason Code extension,
- // because we'll synthesize that ourselves to ensure it is correct.
- exts := make([]pkix.Extension, 0, len(rce.ExtraExtensions))
- for _, ext := range rce.ExtraExtensions {
- if ext.Id.Equal(oidExtensionReasonCode) {
- return nil, errors.New("x509: template contains entry with ReasonCode ExtraExtension; use ReasonCode field instead")
- }
- exts = append(exts, ext)
- }
- // Only add a reasonCode extension if the reason is non-zero, as per
- // RFC 5280 Section 5.3.1.
- if rce.ReasonCode != 0 {
- reasonBytes, err := asn1.Marshal(asn1.Enumerated(rce.ReasonCode))
- if err != nil {
- return nil, err
- }
- exts = append(exts, pkix.Extension{
- Id: oidExtensionReasonCode,
- Value: reasonBytes,
- })
- }
- if len(exts) > 0 {
- rc.Extensions = exts
- }
- revokedCerts[i] = rc
- }
- }
- aki, err := asn1.Marshal(authKeyId{Id: issuer.SubjectKeyId})
- if err != nil {
- return nil, err
- }
- if numBytes := template.Number.Bytes(); len(numBytes) > 20 || (len(numBytes) == 20 && numBytes[0]&0x80 != 0) {
- return nil, errors.New("x509: CRL number exceeds 20 octets")
- }
- crlNum, err := asn1.Marshal(template.Number)
- if err != nil {
- return nil, err
- }
- // Correctly use the issuer's subject sequence if one is specified.
- issuerSubject, err := subjectBytes(issuer)
- if err != nil {
- return nil, err
- }
- tbsCertList := tbsCertificateList{
- Version: 1, // v2
- Signature: signatureAlgorithm,
- Issuer: asn1.RawValue{FullBytes: issuerSubject},
- ThisUpdate: template.ThisUpdate.UTC(),
- NextUpdate: template.NextUpdate.UTC(),
- Extensions: []pkix.Extension{
- {
- Id: oidExtensionAuthorityKeyId,
- Value: aki,
- },
- {
- Id: oidExtensionCRLNumber,
- Value: crlNum,
- },
- },
- }
- if len(revokedCerts) > 0 {
- tbsCertList.RevokedCertificates = revokedCerts
- }
- if len(template.ExtraExtensions) > 0 {
- tbsCertList.Extensions = append(tbsCertList.Extensions, template.ExtraExtensions...)
- }
- tbsCertListContents, err := asn1.Marshal(tbsCertList)
- if err != nil {
- return nil, err
- }
- // Optimization to only marshal this struct once, when signing and
- // then embedding in certificateList below.
- tbsCertList.Raw = tbsCertListContents
- input := tbsCertListContents
- if hashFunc != 0 {
- h := hashFunc.New()
- h.Write(tbsCertListContents)
- input = h.Sum(nil)
- }
- var signerOpts crypto.SignerOpts = hashFunc
- if template.SignatureAlgorithm.isRSAPSS() {
- signerOpts = &rsa.PSSOptions{
- SaltLength: rsa.PSSSaltLengthEqualsHash,
- Hash: hashFunc,
- }
- }
- signature, err := priv.Sign(rand, input, signerOpts)
- if err != nil {
- return nil, err
- }
- return asn1.Marshal(certificateList{
- TBSCertList: tbsCertList,
- SignatureAlgorithm: signatureAlgorithm,
- SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
- })
- }
- // CheckSignatureFrom verifies that the signature on rl is a valid signature
- // from issuer.
- func (rl *RevocationList) CheckSignatureFrom(parent *Certificate) error {
- if parent.Version == 3 && !parent.BasicConstraintsValid ||
- parent.BasicConstraintsValid && !parent.IsCA {
- return ConstraintViolationError{}
- }
- if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCRLSign == 0 {
- return ConstraintViolationError{}
- }
- if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm {
- return ErrUnsupportedAlgorithm
- }
- return parent.CheckSignature(rl.SignatureAlgorithm, rl.RawTBSRevocationList, rl.Signature)
- }
|