Skip to content

Commit 44242a1

Browse files
authored
fix cert loading from eba (#18)
1 parent 4d925ad commit 44242a1

7 files changed

Lines changed: 147 additions & 199 deletions

File tree

app/cert/parse.go

Lines changed: 73 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,11 @@ import (
1212
"strings"
1313
"time"
1414

15-
"github.com/gin-gonic/gin"
1615
"go.mongodb.org/mongo-driver/bson"
1716

1817
"github.com/botsman/tppVerifier/app/models"
1918
)
2019

21-
// type Scope string
22-
23-
// const (
24-
// // PSP_AS Scope = "PSP_AS"
25-
// PSP_PI Scope = "PSP_PI"
26-
// PSP_AI Scope = "PSP_AI"
27-
// // PSP_IC Scope = "PSP_IC"
28-
// )
29-
3020
type PSD2QcType struct {
3121
RolesOfPSP []Role
3222
NCAName string
@@ -38,8 +28,6 @@ type Role struct {
3828
Value models.ObRole
3929
}
4030

41-
42-
4331
type QCStatement struct {
4432
ID asn1.ObjectIdentifier
4533
Value asn1.RawValue `asn1:"optional"`
@@ -52,43 +40,80 @@ type NCA struct {
5240
}
5341

5442
type ParsedCert struct {
55-
Cert *x509.Certificate `json:"-"`
56-
CompanyId string
57-
Scopes []models.Scope
58-
ParentLinks []string
59-
CRLs []string
60-
OCSPs []string
61-
Usage models.CertUsage
62-
Serial string
63-
Sha256 string
64-
NCA NCA
43+
Cert *x509.Certificate `json:"-"`
44+
Registers []models.Register
45+
CreatedAt time.Time
46+
UpdatedAt time.Time
47+
IsActive bool
48+
Position models.Position
6549
}
6650

67-
func (c *ParsedCert) ToBson(now time.Time) (bson.M, error) {
51+
func (c *ParsedCert) ToBson() (bson.M, error) {
6852
if c.Cert == nil {
6953
return nil, errors.New("certificate is nil")
7054
}
7155
res := bson.M{
7256
"pem": c.Cert.Raw,
73-
"serial_number": c.Serial,
74-
"sha256": c.Sha256,
75-
// "links": c.ParentLinks,
57+
"serial_number": c.Cert.SerialNumber.String(),
58+
"sha256": c.Sha256(),
59+
"registers": c.Registers,
7660
"not_before": c.Cert.NotBefore,
7761
"not_after": c.Cert.NotAfter,
78-
"type": c.Usage,
79-
// "position": "intermediate",
80-
// "scopes": c.Scopes,
81-
"nca": c.NCA,
82-
"created_at": now,
83-
"updated_at": now,
62+
"updated_at": c.UpdatedAt,
63+
"position": c.Position,
64+
}
65+
nca, err := c.NCA()
66+
if err != nil {
67+
return nil, err
68+
}
69+
if nca != nil {
70+
res["nca"] = bson.M{
71+
"country": nca.Country,
72+
"name": nca.Name,
73+
"id": nca.Id,
74+
}
75+
}
76+
scopes, err := c.OBScopes()
77+
if err != nil {
78+
return nil, err
8479
}
85-
if c.Scopes != nil {
86-
res["scopes"] = c.Scopes
80+
if scopes != nil {
81+
res["scopes"] = scopes
82+
}
83+
if c.Position == models.Leaf {
84+
res["usage"] = c.Usage()
8785
}
8886
return res, nil
8987
}
9088

91-
func ParseCert(_ *gin.Context, data []byte) (*ParsedCert, error) {
89+
func (c *ParsedCert) UnmarshalBSON(data []byte) error {
90+
var raw bson.M
91+
if err := bson.Unmarshal(data, &raw); err != nil {
92+
return err
93+
}
94+
c.Registers = raw["registers"].([]models.Register)
95+
c.CreatedAt = raw["created_at"].(time.Time)
96+
c.UpdatedAt = raw["updated_at"].(time.Time)
97+
c.IsActive = raw["is_active"].(bool)
98+
c.Position = raw["position"].(models.Position)
99+
100+
pemData := raw["pem"].([]byte)
101+
p, _ := pem.Decode(pemData) // ignore rest for now, maybe use it later
102+
if p == nil {
103+
return errors.New("error parsing certificate")
104+
}
105+
c.Cert, _ = x509.ParseCertificate(p.Bytes) // ignore error for now
106+
return nil
107+
}
108+
109+
func (c *ParsedCert) CompanyId() string {
110+
if c.Cert == nil {
111+
return ""
112+
}
113+
return c.Cert.Subject.SerialNumber
114+
}
115+
116+
func ParseCert(data []byte) (*ParsedCert, error) {
92117
data, err := FormatCertContent(data)
93118
if err != nil {
94119
return nil, err
@@ -103,23 +128,6 @@ func ParseCert(_ *gin.Context, data []byte) (*ParsedCert, error) {
103128
}
104129
var cert ParsedCert
105130
cert.Cert = x509Cert
106-
cert.CompanyId = x509Cert.Subject.SerialNumber
107-
scopes, err := getCertOBScopes(x509Cert)
108-
if err != nil {
109-
return nil, err
110-
}
111-
cert.Scopes = scopes
112-
cert.ParentLinks = x509Cert.IssuingCertificateURL
113-
cert.CRLs = x509Cert.CRLDistributionPoints
114-
cert.OCSPs = x509Cert.OCSPServer
115-
cert.Usage = getCertUsage(x509Cert)
116-
cert.Serial = x509Cert.SerialNumber.String()
117-
cert.Sha256 = GetSha256(x509Cert)
118-
nca, err := getCertNCA(x509Cert)
119-
if err != nil {
120-
return nil, err
121-
}
122-
cert.NCA = nca
123131
return &cert, nil
124132
}
125133

@@ -145,7 +153,7 @@ func FormatCertContent(content []byte) ([]byte, error) {
145153
return buffer.Bytes(), nil
146154
}
147155

148-
func getCertOBScopes(cert *x509.Certificate) ([]models.Scope, error) {
156+
func (c *ParsedCert) OBScopes() ([]models.Scope, error) {
149157
roleToScope := func(role models.ObRole) models.Scope {
150158
switch role {
151159
case "PSP_PI":
@@ -156,7 +164,7 @@ func getCertOBScopes(cert *x509.Certificate) ([]models.Scope, error) {
156164
return models.ScopeUnknown
157165
}
158166
}
159-
for _, ext := range cert.Extensions {
167+
for _, ext := range c.Cert.Extensions {
160168
if !ext.Id.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3}) {
161169
continue
162170
}
@@ -194,34 +202,34 @@ func getCertOBScopes(cert *x509.Certificate) ([]models.Scope, error) {
194202
return nil, nil
195203
}
196204

197-
func getCertUsage(cert *x509.Certificate) models.CertUsage {
205+
func (c *ParsedCert) Usage() models.CertUsage {
198206
// Maybe this should be identified based on certificate policy
199-
switch cert.KeyUsage {
207+
switch c.Cert.KeyUsage {
200208
case x509.KeyUsageKeyEncipherment:
201209
return models.QWAC
202210
case x509.KeyUsageContentCommitment:
203211
return models.QSEAL
204212
default:
205213
// perhaps identify based on the extended key usage or certificate policy
206-
log.Printf("Unknown certificate usage: %v", cert.KeyUsage)
214+
log.Printf("Unknown certificate usage: %v", c.Cert.KeyUsage)
207215
return models.UNKNOWN
208216
}
209217
}
210218

211-
func GetSha256(cert *x509.Certificate) string {
212-
checksum := sha256.Sum256(cert.Raw)
219+
func (c *ParsedCert) Sha256() string {
220+
checksum := sha256.Sum256(c.Cert.Raw)
213221
return hex.EncodeToString(checksum[:])
214222
}
215223

216-
func getCertNCA(cert *x509.Certificate) (NCA, error) {
217-
for _, ext := range cert.Extensions {
224+
func (c *ParsedCert) NCA() (*NCA, error) {
225+
for _, ext := range c.Cert.Extensions {
218226
if !ext.Id.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 3}) {
219227
continue
220228
}
221229
var qcStatements []QCStatement
222230
_, err := asn1.Unmarshal(ext.Value, &qcStatements)
223231
if err != nil {
224-
return NCA{}, err
232+
return nil, err
225233
}
226234

227235
for _, stmt := range qcStatements {
@@ -239,12 +247,12 @@ func getCertNCA(cert *x509.Certificate) (NCA, error) {
239247
var psd2 PSD2QcType
240248
_, err := asn1.Unmarshal(stmt.Value.FullBytes, &psd2)
241249
if err != nil {
242-
return NCA{}, err
250+
return nil, err
243251
}
244252
country := psd2.NCAId[:2]
245-
return NCA{Country: country, Name: psd2.NCAName, Id: psd2.NCAId}, nil
253+
return &NCA{Country: country, Name: psd2.NCAName, Id: psd2.NCAId}, nil
246254
}
247255
}
248256
}
249-
return NCA{}, nil
257+
return nil, nil
250258
}

app/models/models.go

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"fmt"
66
"time"
77
"unicode"
8-
9-
"go.mongodb.org/mongo-driver/bson"
108
)
119

1210
type CertUsage string
@@ -192,46 +190,3 @@ const (
192190
ScopePIS Scope = "PIS"
193191
ScopeUnknown Scope = "UNKNOWN"
194192
)
195-
196-
type ParsedCert struct {
197-
Pem string
198-
SerialNumber string
199-
Sha256 string
200-
Links []string
201-
Registers []Register
202-
NotBefore time.Time
203-
NotAfter time.Time
204-
Type CertUsage
205-
Position Position
206-
Scopes []Scope
207-
RootSha256 *string `bson:"root_sha256,omitempty"` // sha256 of the root certificate, if this is an intermediate or leaf certificate
208-
// CRLs []string ??
209-
CreatedAt time.Time `bson:"created_at"`
210-
UpdatedAt time.Time `bson:"updated_at"`
211-
IsActive bool `bson:"is_active"`
212-
}
213-
214-
func (c ParsedCert) ToBson(now time.Time) (bson.M, error) {
215-
res := bson.M{
216-
"pem": c.Pem,
217-
"serial_number": c.SerialNumber,
218-
"sha256": c.Sha256,
219-
"registers": c.Registers,
220-
"not_before": c.NotBefore,
221-
"not_after": c.NotAfter,
222-
"type": c.Type,
223-
"position": c.Position,
224-
"updated_at": now,
225-
"is_active": true,
226-
}
227-
if c.Links != nil {
228-
res["links"] = c.Links
229-
}
230-
if c.RootSha256 != nil {
231-
res["root_sha256"] = *c.RootSha256
232-
}
233-
if c.Scopes != nil {
234-
res["scopes"] = c.Scopes
235-
}
236-
return res, nil
237-
}

app/verify/verify.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,15 @@ func (s *VerifySvc) Verify(c *gin.Context) {
119119
return
120120
}
121121
result := VerifyResult{}
122-
cert, err := cert.ParseCert(c, req.Cert)
122+
cert, err := cert.ParseCert(req.Cert)
123123
if err != nil {
124124
c.JSON(http.StatusBadRequest, gin.H{
125125
"error": err.Error(),
126126
})
127127
return
128128
}
129129
result.Certificate = cert
130-
tpp, err := s.getTpp(c, cert.CompanyId)
130+
tpp, err := s.getTpp(c, cert.CompanyId())
131131
if err != nil {
132132
c.JSON(http.StatusInternalServerError, gin.H{
133133
"error": err.Error(),
@@ -258,7 +258,7 @@ func (s *VerifySvc) verifyCert(c *gin.Context, crt *cert.ParsedCert) (certVerify
258258
Valid: true,
259259
Reason: "",
260260
}
261-
if crt.Usage == models.UNKNOWN {
261+
if crt.Usage() == models.UNKNOWN {
262262
result.Valid = false
263263
result.Reason = "Unknown certificate usage"
264264
return result, nil
@@ -351,7 +351,7 @@ func (s *VerifySvc) loadCertChain(c *gin.Context, link string) error {
351351
}
352352
// Add the certificate to the intermediate pool
353353
s.AddIntermediate(crt.Cert)
354-
log.Printf("Added certificate with SHA256 %s to the intermediate pool", cert.GetSha256(crt.Cert))
354+
log.Printf("Added certificate with SHA256 %s to the intermediate pool", crt.Sha256())
355355
}
356356
parentCert := certs[len(certs)-1].Cert // Get the last certificate in the chain
357357
if len(parentCert.IssuingCertificateURL) == 0 {
@@ -369,7 +369,7 @@ func (s *VerifySvc) loadCerts(c *gin.Context, body io.ReadCloser) ([]*cert.Parse
369369
log.Printf("Error reading response body: %s", err)
370370
return nil, err
371371
}
372-
crt, err := cert.ParseCert(c, bodyBytes)
372+
crt, err := cert.ParseCert(bodyBytes)
373373
if err != nil {
374374
log.Printf("Error parsing certificate: %s", err)
375375
return nil, err
@@ -396,7 +396,12 @@ func (s *VerifySvc) getScopes(c *gin.Context, crt *cert.ParsedCert, tpp *models.
396396

397397
func getCertServices(crt cert.ParsedCert) []models.Service {
398398
services := make([]models.Service, 0)
399-
for _, scope := range crt.Scopes {
399+
scopes, err := crt.OBScopes()
400+
if err != nil {
401+
log.Printf("Error getting OB scopes from certificate: %s", err)
402+
return nil
403+
}
404+
for _, scope := range scopes {
400405
switch scope {
401406
case models.ScopePIS:
402407
services = append(services, models.PISP)

0 commit comments

Comments
 (0)