From 62962a13c73e626a657ba6d5408cee25997bc27f Mon Sep 17 00:00:00 2001 From: afonso Date: Thu, 30 May 2024 15:48:28 +0100 Subject: [PATCH] [PD2] Made cert checks in cryptoutils --- Projs/PD2/cmd/client/client.go | 2 +- Projs/PD2/cmd/gateway/gateway.go | 2 +- Projs/PD2/cmd/server/server.go | 2 +- Projs/PD2/go.mod | 2 +- Projs/PD2/internal/client/client.go | 6 +- Projs/PD2/internal/gateway/gateway.go | 67 ++++--- Projs/PD2/internal/server/datastore.go | 2 +- Projs/PD2/internal/server/server.go | 27 +-- .../internal/utils/cryptoUtils/cryptoUtils.go | 183 +++++++++++------- 9 files changed, 160 insertions(+), 133 deletions(-) diff --git a/Projs/PD2/cmd/client/client.go b/Projs/PD2/cmd/client/client.go index 9ab182b..64e477e 100644 --- a/Projs/PD2/cmd/client/client.go +++ b/Projs/PD2/cmd/client/client.go @@ -1,7 +1,7 @@ package main import ( - "PD1/internal/client" + "PD2/internal/client" ) func main(){ diff --git a/Projs/PD2/cmd/gateway/gateway.go b/Projs/PD2/cmd/gateway/gateway.go index f23513c..ae37ca9 100644 --- a/Projs/PD2/cmd/gateway/gateway.go +++ b/Projs/PD2/cmd/gateway/gateway.go @@ -1,7 +1,7 @@ package main import ( - "PD1/internal/gateway" + "PD2/internal/gateway" ) func main(){ diff --git a/Projs/PD2/cmd/server/server.go b/Projs/PD2/cmd/server/server.go index c93ba9b..3455da6 100644 --- a/Projs/PD2/cmd/server/server.go +++ b/Projs/PD2/cmd/server/server.go @@ -1,7 +1,7 @@ package main import ( - "PD1/internal/server" + "PD2/internal/server" ) func main(){ diff --git a/Projs/PD2/go.mod b/Projs/PD2/go.mod index 1d04cdb..75190eb 100644 --- a/Projs/PD2/go.mod +++ b/Projs/PD2/go.mod @@ -1,4 +1,4 @@ -module PD1 +module PD2 go 1.22.2 diff --git a/Projs/PD2/internal/client/client.go b/Projs/PD2/internal/client/client.go index f41e223..615e04d 100644 --- a/Projs/PD2/internal/client/client.go +++ b/Projs/PD2/internal/client/client.go @@ -1,9 +1,9 @@ package client import ( - "PD1/internal/protocol" - "PD1/internal/utils/cryptoUtils" - "PD1/internal/utils/networking" + "PD2/internal/protocol" + "PD2/internal/utils/cryptoUtils" + "PD2/internal/utils/networking" "crypto/x509" "errors" "flag" diff --git a/Projs/PD2/internal/gateway/gateway.go b/Projs/PD2/internal/gateway/gateway.go index cd32e3f..44e4de8 100644 --- a/Projs/PD2/internal/gateway/gateway.go +++ b/Projs/PD2/internal/gateway/gateway.go @@ -1,8 +1,8 @@ package gateway import ( - "PD1/internal/protocol" - "PD1/internal/utils/cryptoUtils" + "PD2/internal/protocol" + "PD2/internal/utils/cryptoUtils" "crypto/x509" "fmt" "log" @@ -32,30 +32,30 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke var postRegister protocol.PostRegister err := c.Bind(postRegister) if err != nil { - c.JSON(http.StatusBadRequest,gin.H{"error": "Request body is not a PostRegister"}) - return + c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a PostRegister"}) + return } //Check if the certificate pseudonym matches the uid in postRegister //And if it's signed by the CA userCert, err := x509.ParseCertificate(postRegister.Certificate) if err != nil { - c.JSON(http.StatusBadRequest,gin.H{"error": "User certificate is invalid"}) - return + c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"}) + return } oidMap := cryptoUtils.ExtractAllOIDValues(userCert) //Check if certificate usage is MSG SERVICE usage := oidMap["2.5.4.11"] if usage != "MSG SERVICE" { - c.JSON(http.StatusBadRequest,gin.H{"error": "Certificate usage is not \"MSG SERVICE\""}) - return + c.JSON(http.StatusBadRequest, gin.H{"error": "Certificate usage is not \"MSG SERVICE\""}) + return } - err = keyStore.CheckCert(userCert, postRegister.UID) + err = keyStore.CheckCert(userCert, postRegister.UID, "MSG SERVICE") if err != nil { - c.JSON(http.StatusBadRequest,gin.H{"error": "User certificate is invalid, not trusted or belongs to another user"}) - return + c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid, not trusted, belongs to another user or has incorrect usage field"}) + return } hashedPassword, err := HashPassword(postRegister.Password) @@ -65,10 +65,10 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke err = dataStore.InsertUser(postRegister.UID, hashedPassword) if err != nil { - log.Fatalln("Could not insert user into DB") + log.Fatalln("Could not insert user into DB") } - //TODO: Send the certificate to the server + //TODO: Send the certificate to the server c.JSON(http.StatusOK, gin.H{}) @@ -91,31 +91,30 @@ func HandleLogin(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeySt c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"}) return } - jwToken, err := GenerateJWT(postLogin.UID) + jwToken, err := GenerateJWT(postLogin.UID) - if err != nil { + if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create token"}) - } - //Send token to user - c.JSON(http.StatusOK, gin.H{"token":jwToken}) + } + //Send token to user + c.JSON(http.StatusOK, gin.H{"token": jwToken}) } - func AuthMiddleware(c *gin.Context) { fmt.Println("Authentication Middleware") - tokenList := c.Request.Header["Token"] - if tokenList == nil { - c.JSON(http.StatusUnauthorized,gin.H{"error": "No authentication token provided"}) - } - // We only care about the first entry - token := tokenList[0] - - uid, err := ValidateJWT(token) - if err!= nil { - c.JSON(http.StatusUnauthorized,gin.H{"error": "Token is invalid or has expired"}) - } - c.Set("uid", uid) - c.Next() + tokenList := c.Request.Header["Token"] + if tokenList == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "No authentication token provided"}) + } + // We only care about the first entry + token := tokenList[0] + + uid, err := ValidateJWT(token) + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is invalid or has expired"}) + } + c.Set("uid", uid) + c.Next() } func Run() { @@ -164,10 +163,10 @@ func Run() { server := http.Server{ Addr: "0.0.0.0:8080", Handler: router, - TLSConfig: serverKeyStore.GetServerTLSConfig(), + TLSConfig: keyStore.GetGatewayIncomingTLSConfig(), } - err := server.ListenAndServeTLS("", "") + err = server.ListenAndServeTLS("", "") if err != nil { log.Fatal(err.Error()) } diff --git a/Projs/PD2/internal/server/datastore.go b/Projs/PD2/internal/server/datastore.go index dc8a722..33ec110 100644 --- a/Projs/PD2/internal/server/datastore.go +++ b/Projs/PD2/internal/server/datastore.go @@ -1,7 +1,7 @@ package server import ( - "PD1/internal/protocol" + "PD2/internal/protocol" "crypto/x509" "database/sql" "errors" diff --git a/Projs/PD2/internal/server/server.go b/Projs/PD2/internal/server/server.go index 9066fc9..db0b5a9 100644 --- a/Projs/PD2/internal/server/server.go +++ b/Projs/PD2/internal/server/server.go @@ -1,8 +1,8 @@ package server import ( - "PD1/internal/protocol" - "PD1/internal/utils/cryptoUtils" + "PD2/internal/protocol" + "PD2/internal/utils/cryptoUtils" "log" "net/http" "strconv" @@ -10,29 +10,6 @@ import ( "github.com/gin-gonic/gin" ) -//func clientHandler(connection networking.Connection[protocol.Packet], dataStore DataStore) { -// defer connection.Conn.Close() -// -// //Get certificate sent by user -// clientCert := connection.GetPeerCertificate() -// //Get the OID values -// oidMap := cryptoUtils.ExtractAllOIDValues(clientCert) -// //Check if certificate usage is MSG SERVICE -// usage := oidMap["2.5.4.11"] -// if usage == "" { -// log.Fatalln("User certificate does not have the correct usage") -// } -// //Get the UID of this user -// UID := oidMap["2.5.4.65"] -// if UID == "" { -// log.Fatalln("User certificate does not specify it's PSEUDONYM") -// } -// err := dataStore.storeUserCertIfNotExists(UID, *clientCert) -// if err != nil { -// log.Fatalln(err) -// } -//} - func HandleGetUserCert(c *gin.Context, dataStore DataStore) { user := c.Param("user") userCertPacket, err := dataStore.GetUserCertificate(user) diff --git a/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go b/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go index 6e4d4bb..9b10d7d 100644 --- a/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go +++ b/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go @@ -19,19 +19,15 @@ import ( ) type KeyStore struct { - cert *x509.Certificate - caCertChain []*x509.Certificate - privKey *rsa.PrivateKey + cert *x509.Certificate + caCertPool *x509.CertPool + privKey *rsa.PrivateKey } func (k KeyStore) GetCert() *x509.Certificate { return k.cert } -func (k KeyStore) GetCACertChain() []*x509.Certificate { - return k.caCertChain -} - func (k KeyStore) GetPrivKey() *rsa.PrivateKey { return k.privKey } @@ -67,25 +63,31 @@ func LoadKeyStore(keyStorePath string, password string) (KeyStore, error) { if err := privKey.Validate(); err != nil { return KeyStore{}, err } - return KeyStore{cert: cert, caCertChain: caCerts, privKey: privKey}, err -} -// Check if the cert is signed by the CA and is for the correct user -func (k KeyStore) CheckCert(cert *x509.Certificate, uid string) error { caCertPool := x509.NewCertPool() - for _, caCert := range k.caCertChain { + for _, caCert := range caCerts { caCertPool.AddCert(caCert) } + + return KeyStore{cert: cert, caCertPool: caCertPool, privKey: privKey}, err +} + +// Check if the cert is signed by a known CA +func (k KeyStore) CheckCertCA(cert *x509.Certificate) error { + // Verify the peer's certificate opts := x509.VerifyOptions{ - Roots: caCertPool, + Roots: k.caCertPool, } // Check if the certificate is signed by the specified CA _, err := cert.Verify(opts) if err != nil { - log.Println("Certificate not signed by a trusted CA") - return err + return errors.New("certificate not signed by trusted CA") } + return nil +} +// Check if the cert is valid +func (k KeyStore) CheckCertTime(cert *x509.Certificate) error { if cert.NotAfter.Before(time.Now()) { return errors.New("certificate has expired") } @@ -93,10 +95,37 @@ func (k KeyStore) CheckCert(cert *x509.Certificate, uid string) error { return errors.New("certificate is not valid yet") } - //Check if the pseudonym field is set to UID + return nil +} + +// Check if the pseudonym field is set to the correct pseudonym +func (k KeyStore) CheckCertPseudonym(cert *x509.Certificate, pseudonym string) error { oidMap := ExtractAllOIDValues(cert) - if oidMap["2.5.4.65"] != uid { - log.Println("Certificate does not belong to the message's receiver") + if oidMap["2.5.4.65"] != pseudonym { + return errors.New("Certificate does not belong to the correct pseudonym") + } + return nil +} + +func (k KeyStore) CheckCertUsage(cert *x509.Certificate, usage string) error { + oidMap := ExtractAllOIDValues(cert) + if oidMap["2.5.4.11"] != usage { + return errors.New("Certificate does not have the correct usage") + } + return nil +} + +func (k KeyStore) CheckCert(cert *x509.Certificate, pseudonym string, usage string) error { + if err := k.CheckCertCA(cert); err != nil { + return err + } + if err := k.CheckCertTime(cert); err != nil { + return err + } + if err := k.CheckCertPseudonym(cert, pseudonym); err != nil { + return err + } + if err := k.CheckCertUsage(cert, usage); err != nil { return err } return nil @@ -106,49 +135,58 @@ func (k *KeyStore) GetTLSConfig() *tls.Config { certificate := tls.Certificate{Certificate: [][]byte{k.cert.Raw}, PrivateKey: k.privKey, Leaf: k.cert} - //Add the CA certificate chain to a CertPool - caCertPool := x509.NewCertPool() - for _, caCert := range k.caCertChain { - caCertPool.AddCert(caCert) - } config := &tls.Config{ Certificates: []tls.Certificate{certificate}, } return config } - -func (k *KeyStore) GetServerTLSConfig() *tls.Config { +func (k *KeyStore) GetGatewayIncomingTLSConfig() *tls.Config { tlsConfig := k.GetTLSConfig() - //Add the CA certificate chain to a CertPool - caCertPool := x509.NewCertPool() - for _, caCert := range k.caCertChain { - caCertPool.AddCert(caCert) - } - tlsConfig.ClientCAs = caCertPool tlsConfig.ClientAuth = tls.RequireAnyClientCert tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { - // Verify the peer's certificate - opts := x509.VerifyOptions{ - Roots: caCertPool, - } for _, certBytes := range rawCerts { cert, err := x509.ParseCertificate(certBytes) if err != nil { return err } - - if cert.NotAfter.Before(time.Now()) { - return errors.New("certificate has expired") + if err = k.CheckCertCA(cert); err != nil { + return err } - if cert.NotBefore.After(time.Now()) { - return errors.New("certificate is not valid yet") + if err = k.CheckCertTime(cert); err != nil { + return err } + if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil { + return err + } + } + return nil + } + return tlsConfig +} - // Check if the certificate is signed by the specified CA - _, err = cert.Verify(opts) +func (k *KeyStore) GetGatewayOutgoingTLSConfig() *tls.Config { + tlsConfig := k.GetTLSConfig() + + tlsConfig.RootCAs = k.caCertPool + tlsConfig.InsecureSkipVerify = true + tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { + for _, certBytes := range rawCerts { + cert, err := x509.ParseCertificate(certBytes) if err != nil { - return errors.New("certificate not signed by trusted CA") + return err + } + if err = k.CheckCertCA(cert); err != nil { + return err + } + if err = k.CheckCertTime(cert); err != nil { + return err + } + if err = k.CheckCertPseudonym(cert, "SERVER"); err != nil { + return err + } + if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil { + return err } } return nil @@ -159,41 +197,54 @@ func (k *KeyStore) GetServerTLSConfig() *tls.Config { func (k *KeyStore) GetClientTLSConfig() *tls.Config { tlsConfig := k.GetTLSConfig() - //Add the CA certificate chain to a CertPool - caCertPool := x509.NewCertPool() - for _, caCert := range k.caCertChain { - caCertPool.AddCert(caCert) - } - tlsConfig.RootCAs = caCertPool + tlsConfig.RootCAs = k.caCertPool tlsConfig.InsecureSkipVerify = true tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { - // Verify the peer's certificate - opts := x509.VerifyOptions{ - Roots: caCertPool, - } for _, certBytes := range rawCerts { cert, err := x509.ParseCertificate(certBytes) if err != nil { return err } - - if cert.NotAfter.Before(time.Now()) { - return errors.New("certificate has expired") + if err = k.CheckCertCA(cert); err != nil { + return err } - if cert.NotBefore.After(time.Now()) { - return errors.New("certificate is not valid yet") + if err = k.CheckCertTime(cert); err != nil { + return err + } + if err = k.CheckCertPseudonym(cert, "GATEWAY"); err != nil { + return err + } + if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil { + return err } - oidMap := ExtractAllOIDValues(cert) - // Check if the certificate is signed by the specified CA - _, err = cert.Verify(opts) + } + return nil + } + return tlsConfig +} + +func (k *KeyStore) GetServerTLSConfig() *tls.Config { + tlsConfig := k.GetTLSConfig() + + tlsConfig.ClientAuth = tls.RequireAnyClientCert + tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { + for _, certBytes := range rawCerts { + cert, err := x509.ParseCertificate(certBytes) if err != nil { - return errors.New("certificate not signed by trusted CA") + return err } - - //Check if the pseudonym field is set to "SERVER" - if oidMap["2.5.4.65"] != "SERVER" { - return errors.New("peer isn't the server") + if err = k.CheckCertCA(cert); err != nil { + return err + } + if err = k.CheckCertTime(cert); err != nil { + return err + } + if err = k.CheckCertPseudonym(cert, "GATEWAY"); err != nil { + return err + } + if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil { + return err } } return nil