...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package x509tools
18
19 import (
20 "crypto"
21 "crypto/rsa"
22 "crypto/x509/pkix"
23 "encoding/asn1"
24 "errors"
25 )
26
27
28
29 type pssParameters struct {
30
31
32
33 Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"`
34 MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"`
35 SaltLength int `asn1:"explicit,tag:2"`
36 TrailerField int `asn1:"optional,explicit,tag:3,default:1"`
37 }
38
39 func MarshalRSAPSSParameters(pub *rsa.PublicKey, opts *rsa.PSSOptions) (asn1.RawValue, error) {
40 hashAlg, ok := PkixDigestAlgorithm(opts.Hash)
41 if !ok {
42 return asn1.RawValue{}, errors.New("unsupported digest algorithm")
43 }
44 hashRaw, err := asn1.Marshal(hashAlg)
45 if err != nil {
46 return asn1.RawValue{}, err
47 }
48 saltLength := opts.SaltLength
49 switch saltLength {
50 case rsa.PSSSaltLengthAuto:
51 saltLength = (pub.N.BitLen()+7)/8 - 2 - opts.Hash.Size()
52 case rsa.PSSSaltLengthEqualsHash:
53 saltLength = opts.Hash.Size()
54 }
55 params := pssParameters{
56 Hash: hashAlg,
57 MGF: pkix.AlgorithmIdentifier{
58 Algorithm: OidMGF1,
59 Parameters: asn1.RawValue{FullBytes: hashRaw},
60 },
61 SaltLength: saltLength,
62 TrailerField: 1,
63 }
64 serialized, err := asn1.Marshal(params)
65 if err != nil {
66 return asn1.RawValue{}, err
67 }
68 return asn1.RawValue{FullBytes: serialized}, nil
69 }
70
71 func UnmarshalRSAPSSParameters(hash crypto.Hash, raw asn1.RawValue) (*rsa.PSSOptions, error) {
72 hashOid, ok := HashOids[hash]
73 if !ok {
74 return nil, errors.New("unsupported digest algorithm")
75 }
76 if raw.Tag == asn1.TagNull {
77
78 if hash != crypto.SHA1 {
79 return nil, errors.New("RSA-PSS parameters not provided but digest type is not SHA-1")
80 }
81 return &rsa.PSSOptions{Hash: crypto.SHA1, SaltLength: 20}, nil
82 }
83 var params pssParameters
84 if rest, err := asn1.Unmarshal(raw.FullBytes, ¶ms); err != nil || len(rest) > 0 {
85 return nil, errors.New("invalid RSA-PSS parameters")
86 }
87
88 if !params.Hash.Algorithm.Equal(hashOid) {
89 return nil, errors.New("digest type mismatch in RSA-PSS parameters")
90 }
91 if !params.MGF.Algorithm.Equal(OidMGF1) {
92 return nil, errors.New("unsupported MGF in RSA-PSS parameters")
93 }
94 var mgfDigest pkix.AlgorithmIdentifier
95 if rest, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgfDigest); err != nil || len(rest) > 0 {
96 return nil, errors.New("invalid RSA-PSS parameters")
97 }
98 if !mgfDigest.Algorithm.Equal(hashOid) {
99 return nil, errors.New("digest type mismatch in RSA-PSS parameters")
100 }
101 if params.TrailerField != 0 && params.TrailerField != 1 {
102 return nil, errors.New("invalid RSA-PSS parameters")
103 }
104 if params.SaltLength == 0 {
105 params.SaltLength = hash.Size()
106 }
107 return &rsa.PSSOptions{Hash: hash, SaltLength: params.SaltLength}, nil
108 }
109
View as plain text