diff --git a/smx509/parser.go b/smx509/parser.go index 28fcefc..bac32c8 100644 --- a/smx509/parser.go +++ b/smx509/parser.go @@ -233,13 +233,15 @@ func parseExtension(der cryptobyte.String) (pkix.Extension, error) { return ext, nil } -func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { +func parsePublicKey(keyData *publicKeyInfo) (interface{}, error) { + oid := keyData.Algorithm.Algorithm + params := keyData.Algorithm.Parameters der := cryptobyte.String(keyData.PublicKey.RightAlign()) - switch algo { - case RSA: + switch { + case oid.Equal(oidPublicKeyRSA): // RSA public keys must have a NULL in the parameters. // See RFC 3279, Section 2.3.1. - if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) { + if !bytes.Equal(params.FullBytes, asn1.NullBytes) { return nil, errors.New("x509: RSA key missing NULL parameters") } @@ -266,8 +268,8 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ N: p.N, } return pub, nil - case ECDSA: - paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes) + case oid.Equal(oidPublicKeyECDSA): + paramsDer := cryptobyte.String(params.FullBytes) namedCurveOID := new(asn1.ObjectIdentifier) if !paramsDer.ReadASN1ObjectIdentifier(namedCurveOID) { return nil, errors.New("x509: invalid ECDSA parameters") @@ -286,17 +288,25 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ Y: y, } return pub, nil - case Ed25519: + case oid.Equal(oidPublicKeyEd25519): // RFC 8410, Section 3 // > For all of the OIDs, the parameters MUST be absent. - if len(keyData.Algorithm.Parameters.FullBytes) != 0 { + if len(params.FullBytes) != 0 { return nil, errors.New("x509: Ed25519 key encoded with illegal parameters") } if len(der) != ed25519.PublicKeySize { return nil, errors.New("x509: wrong Ed25519 public key size") } return ed25519.PublicKey(der), nil - case DSA: + //TODO: will enable it since golang 1.19.x + //case oid.Equal(oidPublicKeyX25519): + // RFC 8410, Section 3 + // > For all of the OIDs, the parameters MUST be absent. + // if len(params.FullBytes) != 0 { + // return nil, errors.New("x509: X25519 key encoded with illegal parameters") + // } + // return ecdh.X25519().NewPublicKey(der) + case oid.Equal(oidPublicKeyDSA): y := new(big.Int) if !der.ReadASN1Integer(y) { return nil, errors.New("x509: invalid DSA public key") @@ -309,7 +319,7 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ G: new(big.Int), }, } - paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes) + paramsDer := cryptobyte.String(params.FullBytes) if !paramsDer.ReadASN1(¶msDer, cryptobyte_asn1.SEQUENCE) || !paramsDer.ReadASN1Integer(pub.Parameters.P) || !paramsDer.ReadASN1Integer(pub.Parameters.Q) || @@ -322,7 +332,7 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ } return pub, nil default: - return nil, nil + return nil, errors.New("x509: unknown public key algorithm") } } @@ -929,12 +939,14 @@ func parseCertificate(der []byte) (*Certificate, error) { if !spki.ReadASN1BitString(&spk) { return nil, errors.New("x509: malformed subjectPublicKey") } - cert.PublicKey, err = parsePublicKey(cert.PublicKeyAlgorithm, &publicKeyInfo{ - Algorithm: pkAI, - PublicKey: spk, - }) - if err != nil { - return nil, err + if cert.PublicKeyAlgorithm != UnknownPublicKeyAlgorithm { + cert.PublicKey, err = parsePublicKey(&publicKeyInfo{ + Algorithm: pkAI, + PublicKey: spk, + }) + if err != nil { + return nil, err + } } if cert.Version > 1 { diff --git a/smx509/x509.go b/smx509/x509.go index 6a6eae2..e33b3af 100644 --- a/smx509/x509.go +++ b/smx509/x509.go @@ -78,11 +78,7 @@ func ParsePKIXPublicKey(derBytes []byte) (interface{}, error) { } else if len(rest) != 0 { return nil, errors.New("x509: trailing data after ASN.1 of public-key") } - algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm) - if algo == UnknownPublicKeyAlgorithm { - return nil, errors.New("x509: unknown public key algorithm") - } - return parsePublicKey(algo, &pki) + return parsePublicKey(&pki) } func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) { @@ -235,7 +231,7 @@ const ( UnknownPublicKeyAlgorithm = x509.UnknownPublicKeyAlgorithm RSA = x509.RSA - DSA = x509.DSA // Unsupported. + DSA = x509.DSA // Only supported for parsing. ECDSA = x509.ECDSA Ed25519 = x509.Ed25519 ) @@ -434,27 +430,34 @@ func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm return UnknownSignatureAlgorithm } -// 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 } -// -// 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 } var ( - oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} - oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1} - oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} - oidPublicKeyEd25519 = oidSignatureEd25519 + // 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): @@ -1388,6 +1391,10 @@ func CreateCertificate(rand io.Reader, template, parent *x509.Certificate, pub, 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 @@ -1902,9 +1909,11 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error } var err error - out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCSR.PublicKey) - if err != nil { - return nil, err + if out.PublicKeyAlgorithm != UnknownPublicKeyAlgorithm { + out.PublicKey, err = parsePublicKey(&in.TBSCSR.PublicKey) + if err != nil { + return nil, err + } } var subject pkix.RDNSequence