@@ -14,6 +14,7 @@ import (
14
14
"context"
15
15
"crypto/rand"
16
16
"crypto/rsa"
17
+ "crypto/sha1"
17
18
"crypto/x509"
18
19
"crypto/x509/pkix"
19
20
"encoding/asn1"
@@ -45,9 +46,11 @@ func fetchCAInfo(ctx context.Context, req *logical.Request, b *keyfactorBackend)
45
46
}
46
47
47
48
caEntry , err := req .Storage .Get (ctx , "ca" )
49
+
48
50
if err != nil {
49
51
return logical .ErrorResponse ("error fetching ca: %s" , err ), nil
50
52
}
53
+
51
54
if caEntry != nil {
52
55
var r map [string ]interface {}
53
56
json .Unmarshal (caEntry .Value , & r )
@@ -59,8 +62,13 @@ func fetchCAInfo(ctx context.Context, req *logical.Request, b *keyfactorBackend)
59
62
return resp , nil
60
63
}
61
64
62
- // if not we search certs for 'CA -eq "<ca_name>" AND CertState -eq "6"'
63
- //
65
+ // if not, we retreive the CA entry from the "CertificateAuthorities" endpoint
66
+
67
+ // then we look up certs with CertificateAuthorityId = the CA ID.
68
+
69
+ // if at least one exists, we download the cert and chain
70
+
71
+ // if not; we can't get it yet; return appropriate error
64
72
65
73
caId , err := getCAId (ctx , req , b )
66
74
if err != nil {
@@ -404,6 +412,52 @@ func normalizeSerial(serial string) string {
404
412
return strings .Replace (strings .ToLower (serial ), ":" , "-" , - 1 )
405
413
}
406
414
415
+ // ensureCorrectOrder ensures the correct order of the certificate chain using a known leaf thumbprint
416
+ func ensureCorrectOrder (chain []* x509.Certificate , leafThumbprint string ) []* x509.Certificate {
417
+ var leaf * x509.Certificate
418
+ var intermediates []* x509.Certificate
419
+ var root * x509.Certificate
420
+
421
+ // Identify the leaf, intermediate(s), and root
422
+ for _ , cert := range chain {
423
+ if cert .CheckSignatureFrom (cert ) == nil {
424
+ root = cert // Verified self-signed root
425
+ } else if getCertThumbprint (cert ) == leafThumbprint {
426
+ leaf = cert
427
+ } else {
428
+ intermediates = append (intermediates , cert )
429
+ }
430
+ }
431
+
432
+ // Sort intermediates by issuer-subject relationship
433
+ sortedIntermediates := make ([]* x509.Certificate , 0 , len (intermediates ))
434
+ remaining := append ([]* x509.Certificate {}, intermediates ... )
435
+
436
+ for len (remaining ) > 0 {
437
+ for i , cert := range remaining {
438
+ if len (sortedIntermediates ) == 0 || sortedIntermediates [len (sortedIntermediates )- 1 ].Subject .String () == cert .Issuer .String () {
439
+ sortedIntermediates = append (sortedIntermediates , cert )
440
+ remaining = append (remaining [:i ], remaining [i + 1 :]... )
441
+ break
442
+ }
443
+ }
444
+ }
445
+
446
+ // Construct ordered chain
447
+ orderedChain := []* x509.Certificate {leaf }
448
+ orderedChain = append (orderedChain , sortedIntermediates ... )
449
+ if root != nil {
450
+ orderedChain = append (orderedChain , root )
451
+ }
452
+ return orderedChain
453
+ }
454
+
455
+ // getCertThumbprint computes the SHA-1 thumbprint of a certificate
456
+ func getCertThumbprint (cert * x509.Certificate ) string {
457
+ hash := sha1 .Sum (cert .Raw )
458
+ return fmt .Sprintf ("%x" , hash )
459
+ }
460
+
407
461
type KeyfactorCertResponse []struct {
408
462
ID int `json:"Id"`
409
463
Thumbprint string `json:"Thumbprint"`
0 commit comments