func (client *clientImpl) validateTCert(tCertDER []byte) (*x509.Certificate, error) { client.node.log.Debug("Validating TCert [%s]", utils.EncodeBase64(tCertDER)) // DER to x509 x509Cert, err := utils.DERToX509Certificate(tCertDER) if err != nil { client.node.log.Debug("Failed parsing certificate: [%s].", err) return nil, err } // Handle Critical Extension TCertEncTCertIndex if _, err = utils.GetCriticalExtension(x509Cert, utils.TCertEncTCertIndex); err != nil { client.node.log.Error("Failed getting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return nil, err } // Verify certificate against root if _, err := utils.CheckCertAgainRoot(x509Cert, client.node.tcaCertPool); err != nil { client.node.log.Warning("Warning verifing certificate [%s].", err.Error()) return nil, err } return x509Cert, nil }
func (validator *validatorImpl) getEnrollmentCert(id []byte) (*x509.Certificate, error) { sid := utils.EncodeBase64(id) validator.peer.node.log.Debug("Getting enrollment certificate for [%d]", sid) if cert := validator.enrollCerts[sid]; cert != nil { validator.peer.node.log.Debug("Enrollment certificate for [%d] already in memory.", sid) return cert, nil } // Retrieve from the DB or from the ECA in case validator.peer.node.log.Debug("Retrieve Enrollment certificate for [%d]...", sid) rawCert, err := validator.peer.node.ks.GetSignEnrollmentCert(id, validator.getEnrollmentCertByHashFromECA) if err != nil { validator.peer.node.log.Error("Failed getting enrollment certificate for [%s]: [%s]", sid, err) } validator.peer.node.log.Debug("Enrollment certificate for [%s] = [%s]", sid, utils.EncodeBase64(rawCert)) cert, err := utils.DERToX509Certificate(rawCert) if err != nil { validator.peer.node.log.Error("Failed parsing enrollment certificate for [%s]: [%s],[%s]", sid, utils.EncodeBase64(rawCert), err) } validator.enrollCerts[sid] = cert return cert, nil }
func (validator *validatorImpl) getEnrollmentCert(id []byte) (*x509.Certificate, error) { if len(id) == 0 { return nil, fmt.Errorf("Invalid peer id. It is empty.") } sid := utils.EncodeBase64(id) validator.debug("Getting enrollment certificate for [%s]", sid) if cert := validator.enrollCerts[sid]; cert != nil { validator.debug("Enrollment certificate for [%s] already in memory.", sid) return cert, nil } // Retrieve from the DB or from the ECA in case validator.debug("Retrieve Enrollment certificate for [%s]...", sid) rawCert, err := validator.ks.GetSignEnrollmentCert(id, validator.getEnrollmentCertByHashFromECA) if err != nil { validator.error("Failed getting enrollment certificate for [%s]: [%s]", sid, err) return nil, err } cert, err := utils.DERToX509Certificate(rawCert) if err != nil { validator.error("Failed parsing enrollment certificate for [%s]: [% x],[% x]", sid, rawCert, err) return nil, err } validator.enrollCerts[sid] = cert return cert, nil }
func (node *nodeImpl) retrieveTCACertsChain(userID string) error { // Retrieve TCA certificate and verify it tcaCertRaw, err := node.getTCACertificate() if err != nil { node.log.Error("Failed getting TCA certificate [%s].", err.Error()) return err } node.log.Debug("TCA certificate [%s]", utils.EncodeBase64(tcaCertRaw)) // TODO: Test TCA cert againt root CA _, err = utils.DERToX509Certificate(tcaCertRaw) if err != nil { node.log.Error("Failed parsing TCA certificate [%s].", err.Error()) return err } // Store TCA cert node.log.Debug("Storing TCA certificate for validator [%s]...", userID) err = ioutil.WriteFile(node.conf.getTCACertsChainPath(), utils.DERCertToPEM(tcaCertRaw), 0700) if err != nil { node.log.Error("Failed storing tca certificate [%s].", err.Error()) return err } return nil }
func (node *nodeImpl) retrieveECACertsChain(userID string) error { // Retrieve ECA certificate and verify it ecaCertRaw, err := node.getECACertificate() if err != nil { node.log.Error("Failed getting ECA certificate [%s].", err.Error()) return err } node.log.Debug("ECA certificate [%s].", utils.EncodeBase64(ecaCertRaw)) // TODO: Test ECA cert againt root CA // TODO: check responce.Cert against rootCA x509ECACert, err := utils.DERToX509Certificate(ecaCertRaw) if err != nil { node.log.Error("Failed parsing ECA certificate [%s].", err.Error()) return err } // Prepare ecaCertPool node.ecaCertPool = x509.NewCertPool() node.ecaCertPool.AddCert(x509ECACert) // Store ECA cert node.log.Debug("Storing ECA certificate for [%s]...", userID) if err := node.ks.storeCert(node.conf.getECACertsChainFilename(), ecaCertRaw); err != nil { node.log.Error("Failed storing eca certificate [%s].", err.Error()) return err } return nil }
func (client *clientImpl) getTCertFromExternalDER(der []byte) (tCert, error) { // DER to x509 x509Cert, err := utils.DERToX509Certificate(der) if err != nil { client.debug("Failed parsing certificate [% x]: [%s].", der, err) return nil, err } // Handle Critical Extension TCertEncTCertIndex if _, err = utils.GetCriticalExtension(x509Cert, utils.TCertEncTCertIndex); err != nil { client.error("Failed getting extension TCERT_ENC_TCERTINDEX [% x]: [%s].", der, err) return nil, err } // Verify certificate against root if _, err := utils.CheckCertAgainRoot(x509Cert, client.tcaCertPool); err != nil { client.warning("Warning verifing certificate [% x]: [%s].", der, err) return nil, err } return &tCertImpl{client, x509Cert, nil}, nil }
func (node *nodeImpl) retrieveTCACertsChain(userID string) error { // Retrieve TCA certificate and verify it tcaCertRaw, err := node.getTCACertificate() if err != nil { node.error("Failed getting TCA certificate [%s].", err.Error()) return err } node.debug("TCA certificate [% x]", tcaCertRaw) // TODO: Test TCA cert againt root CA _, err = utils.DERToX509Certificate(tcaCertRaw) if err != nil { node.error("Failed parsing TCA certificate [%s].", err.Error()) return err } // Store TCA cert node.debug("Storing TCA certificate for [%s]...", userID) if err := node.ks.storeCert(node.conf.getTCACertsChainFilename(), tcaCertRaw); err != nil { node.error("Failed storing tca certificate [%s].", err.Error()) return err } return nil }
func (node *nodeImpl) getTLSCertificateFromTLSCA(id, affiliation string) (interface{}, []byte, error) { node.log.Info("getTLSCertificate...") priv, err := utils.NewECDSAKey() if err != nil { node.log.Error("Failed generating key: %s", err) return nil, nil, err } uuid, err := util.GenerateUUID() if err != nil { node.log.Error("Failed generating uuid: %s", err) return nil, nil, err } // Prepare the request pubraw, _ := x509.MarshalPKIXPublicKey(&priv.PublicKey) now := time.Now() timestamp := google_protobuf.Timestamp{int64(now.Second()), int32(now.Nanosecond())} req := &obcca.TLSCertCreateReq{ ×tamp, &obcca.Identity{Id: id + "-" + uuid}, &obcca.Password{Pw: ""}, &obcca.PublicKey{ Type: obcca.CryptoType_ECDSA, Key: pubraw, }, nil} rawreq, _ := proto.Marshal(req) r, s, err := ecdsa.Sign(rand.Reader, priv, utils.Hash(rawreq)) if err != nil { panic(err) } R, _ := r.MarshalText() S, _ := s.MarshalText() req.Sig = &obcca.Signature{obcca.CryptoType_ECDSA, R, S} pbCert, err := node.callTLSCACreateCertificate(context.Background(), req) if err != nil { node.log.Error("Failed requesting tls certificate: %s", err) return nil, nil, err } node.log.Info("Verifing tls certificate...") tlsCert, err := utils.DERToX509Certificate(pbCert.Cert) certPK := tlsCert.PublicKey.(*ecdsa.PublicKey) utils.VerifySignCapability(priv, certPK) node.log.Info("Verifing tls certificate...done!") return priv, pbCert.Cert, nil }
func (client *clientImpl) signUsingTCertDER(tCertDER []byte, msg []byte) ([]byte, error) { // Parse the DER tCert, err := utils.DERToX509Certificate(tCertDER) if err != nil { client.node.log.Error("Failed parsing TCert DER [%s].", err.Error()) return nil, err } return client.signUsingTCertX509(tCert, msg) }
func (validator *validatorImpl) verifyValidityPeriod(tx *obc.Transaction) (*obc.Transaction, error) { if tx.Cert != nil && tx.Signature != nil { // Unmarshal cert cert, err := utils.DERToX509Certificate(tx.Cert) if err != nil { validator.peer.node.log.Error("verifyValidityPeriod: failed unmarshalling cert %s:", err) return tx, err } cid := viper.GetString("pki.validity-period.chaincodeHash") ledger, err := ledger.GetLedger() if err != nil { validator.peer.node.log.Error("verifyValidityPeriod: failed getting access to the ledger %s:", err) return tx, err } vp_bytes, err := ledger.GetState(cid, "system.validity.period", true) if err != nil { validator.peer.node.log.Error("verifyValidityPeriod: failed reading validity period from the ledger %s:", err) return tx, err } i, err := strconv.ParseInt(string(vp_bytes[:]), 10, 64) if err != nil { validator.peer.node.log.Error("verifyValidityPeriod: failed to parse validity period %s:", err) return tx, err } vp := time.Unix(i, 0) var errMsg string = "" // Verify the validity period of the TCert switch { case cert.NotAfter.Before(cert.NotBefore): errMsg = "verifyValidityPeriod: certificate validity period is invalid" case vp.Before(cert.NotBefore): errMsg = "verifyValidityPeriod: certificate validity period is in the future" case vp.After(cert.NotAfter): errMsg = "verifyValidityPeriod: certificate validity period is in the past" } if errMsg != "" { validator.peer.node.log.Error(errMsg) return tx, errors.New(errMsg) } } return tx, nil }
func (handler *tCertHandlerImpl) initDER(client *clientImpl, tCertDER []byte) error { // Parse the DER tCert, err := utils.DERToX509Certificate(tCertDER) if err != nil { client.node.log.Error("Failed parsing TCert DER [%s].", err.Error()) return err } handler.initX509(client, tCert) return nil }
// TransactionPreValidation verifies that the transaction is // well formed with the respect to the security layer // prescriptions (i.e. signature verification). func (peer *peerImpl) TransactionPreValidation(tx *obc.Transaction) (*obc.Transaction, error) { if !peer.isInitialized { return nil, utils.ErrNotInitialized } // peer.debug("Pre validating [%s].", tx.String()) peer.debug("Tx confdential level [%s].", tx.ConfidentialityLevel.String()) if tx.Cert != nil && tx.Signature != nil { // Verify the transaction // 1. Unmarshal cert cert, err := utils.DERToX509Certificate(tx.Cert) if err != nil { peer.error("TransactionPreExecution: failed unmarshalling cert [%s] [%s].", err.Error()) return tx, err } // TODO: verify cert // 3. Marshall tx without signature signature := tx.Signature tx.Signature = nil rawTx, err := proto.Marshal(tx) if err != nil { peer.error("TransactionPreExecution: failed marshaling tx [%s] [%s].", err.Error()) return tx, err } tx.Signature = signature // 2. Verify signature ok, err := peer.verify(cert.PublicKey, rawTx, tx.Signature) if err != nil { peer.error("TransactionPreExecution: failed marshaling tx [%s] [%s].", err.Error()) return tx, err } if !ok { return tx, utils.ErrInvalidTransactionSignature } } else { if tx.Cert == nil { return tx, utils.ErrTransactionCertificate } if tx.Signature == nil { return tx, utils.ErrTransactionSignature } } return tx, nil }
func (validator *validatorImpl) getEnrollmentCertByHashFromECA(id []byte) ([]byte, []byte, error) { // Prepare the request validator.peer.node.log.Debug("Reading certificate for hash [%s]", utils.EncodeBase64(id)) req := &obcca.Hash{Hash: id} responce, err := validator.peer.node.callECAReadCertificateByHash(context.Background(), req) if err != nil { validator.peer.node.log.Error("Failed requesting enrollment certificate [%s].", err.Error()) return nil, nil, err } validator.peer.node.log.Debug("Certificate for hash [%s] = [%s][%s]", utils.EncodeBase64(id), utils.EncodeBase64(responce.Sign), utils.EncodeBase64(responce.Enc)) // Verify responce.Sign x509Cert, err := utils.DERToX509Certificate(responce.Sign) if err != nil { validator.peer.node.log.Error("Failed parsing signing enrollment certificate for encrypting: [%s]", err) return nil, nil, err } // Check role roleRaw, err := utils.GetCriticalExtension(x509Cert, ECertSubjectRole) if err != nil { validator.peer.node.log.Error("Failed parsing ECertSubjectRole in enrollment certificate for signing: [%s]", err) return nil, nil, err } role, err := strconv.ParseInt(string(roleRaw), 10, len(roleRaw)*8) if err != nil { validator.peer.node.log.Error("Failed parsing ECertSubjectRole in enrollment certificate for signing: [%s]", err) return nil, nil, err } if obcca.Role(role) != obcca.Role_VALIDATOR { validator.peer.node.log.Error("Invalid ECertSubjectRole in enrollment certificate for signing. Not a validator: [%s]", err) return nil, nil, err } return responce.Sign, responce.Enc, nil }
// CheckTransaction is used to verify that a transaction // is well formed with the respect to the security layer // prescriptions. To be used for internal verifications. func (client *clientImpl) checkTransaction(tx *obc.Transaction) error { if !client.isInitialized { return utils.ErrNotInitialized } if tx.Cert == nil && tx.Signature == nil { return utils.ErrTransactionMissingCert } if tx.Cert != nil && tx.Signature != nil { // Verify the transaction // 1. Unmarshal cert cert, err := utils.DERToX509Certificate(tx.Cert) if err != nil { client.node.log.Error("Failed unmarshalling cert [%s].", err.Error()) return err } // TODO: verify cert // 3. Marshall tx without signature signature := tx.Signature tx.Signature = nil rawTx, err := proto.Marshal(tx) if err != nil { client.node.log.Error("Failed marshaling tx [%s].", err.Error()) return err } tx.Signature = signature // 2. Verify signature ver, err := client.node.verify(cert.PublicKey, rawTx, tx.Signature) if err != nil { client.node.log.Error("Failed marshaling tx [%s].", err.Error()) return err } if ver { return nil } return utils.ErrInvalidTransactionSignature } return utils.ErrTransactionMissingCert }
func (validator *validatorImpl) getEnrollmentCert(id []byte) (*x509.Certificate, error) { sid := utils.EncodeBase64(id) if cert := validator.enrollCerts[sid]; cert != nil { return cert, nil } // Retrieve from the DB or from the ECA in case rawCert, err := validator.peer.node.ks.GetEnrollmentCert(id, validator.getEnrollmentCertByHashFromECA) if err != nil { validator.peer.node.log.Error("Failed getting enrollment certificate for ", sid, err) } cert, err := utils.DERToX509Certificate(rawCert) if err != nil { validator.peer.node.log.Error("Failed parsing enrollment certificate for ", sid, utils.EncodeBase64(rawCert)) } validator.enrollCerts[sid] = cert return cert, nil }
func (client *clientImpl) getTCertFromDER(der []byte) (tCert tCert, err error) { if client.tCertOwnerKDFKey == nil { return nil, fmt.Errorf("KDF key not initialized yet") } TCertOwnerEncryptKey := utils.HMACTruncated(client.tCertOwnerKDFKey, []byte{1}, utils.AESKeyLength) ExpansionKey := utils.HMAC(client.tCertOwnerKDFKey, []byte{2}) // DER to x509 x509Cert, err := utils.DERToX509Certificate(der) if err != nil { client.debug("Failed parsing certificate [% x]: [%s].", der, err) return } // Handle Critical Extenstion TCertEncTCertIndex tCertIndexCT, err := utils.GetCriticalExtension(x509Cert, utils.TCertEncTCertIndex) if err != nil { client.error("Failed getting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return } // Verify certificate against root if _, err = utils.CheckCertAgainRoot(x509Cert, client.tcaCertPool); err != nil { client.warning("Warning verifing certificate [%s].", err.Error()) return } // Verify public key // 384-bit ExpansionValue = HMAC(Expansion_Key, TCertIndex) // Let TCertIndex = Timestamp, RandValue, 1,2,… // Timestamp assigned, RandValue assigned and counter reinitialized to 1 per batch // Decrypt ct to TCertIndex (TODO: || EnrollPub_Key || EnrollID ?) pt, err := utils.CBCPKCS7Decrypt(TCertOwnerEncryptKey, tCertIndexCT) if err != nil { client.error("Failed decrypting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return } // Compute ExpansionValue based on TCertIndex TCertIndex := pt // TCertIndex := []byte(strconv.Itoa(i)) client.debug("TCertIndex: [% x].", TCertIndex) mac := hmac.New(utils.NewHash, ExpansionKey) mac.Write(TCertIndex) ExpansionValue := mac.Sum(nil) // Derive tpk and tsk accordingly to ExapansionValue from enrollment pk,sk // Computable by TCA / Auditor: TCertPub_Key = EnrollPub_Key + ExpansionValue G // using elliptic curve point addition per NIST FIPS PUB 186-4- specified P-384 // Compute temporary secret key tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: client.enrollPrivKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(ExpansionValue) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(client.enrollPrivKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(client.enrollPrivKey.D, k) tempSK.D.Mod(tempSK.D, client.enrollPrivKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := client.enrollPrivKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( client.enrollPrivKey.PublicKey.X, client.enrollPrivKey.PublicKey.Y, tempX, tempY, ) // Verify temporary public key is a valid point on the reference curve isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y) if !isOn { client.error("Failed temporary public key IsOnCurve check.") return nil, fmt.Errorf("Failed temporary public key IsOnCurve check.") } // Check that the derived public key is the same as the one in the certificate certPK := x509Cert.PublicKey.(*ecdsa.PublicKey) if certPK.X.Cmp(tempSK.PublicKey.X) != 0 { client.error("Derived public key is different on X") return nil, fmt.Errorf("Derived public key is different on X") } if certPK.Y.Cmp(tempSK.PublicKey.Y) != 0 { client.error("Derived public key is different on Y") return nil, fmt.Errorf("Derived public key is different on Y") } // Verify the signing capability of tempSK err = utils.VerifySignCapability(tempSK, x509Cert.PublicKey) if err != nil { client.error("Failed verifing signing capability [%s].", err.Error()) return } // Marshall certificate and secret key to be stored in the database if err != nil { client.error("Failed marshalling private key [%s].", err.Error()) return } if err = utils.CheckCertPKAgainstSK(x509Cert, interface{}(tempSK)); err != nil { client.error("Failed checking TCA cert PK against private key [%s].", err.Error()) return } tCert = &tCertImpl{client, x509Cert, tempSK} return }
func (node *nodeImpl) getEnrollmentCertificateFromECA(id, pw string) (interface{}, []byte, []byte, error) { // Get a new ECA Client sock, ecaP, err := node.getECAClient() defer sock.Close() // Run the protocol signPriv, err := utils.NewECDSAKey() if err != nil { node.log.Error("Failed generating ECDSA key [%s].", err.Error()) return nil, nil, nil, err } signPub, err := x509.MarshalPKIXPublicKey(&signPriv.PublicKey) if err != nil { node.log.Error("Failed mashalling ECDSA key [%s].", err.Error()) return nil, nil, nil, err } encPriv, err := utils.NewECDSAKey() if err != nil { node.log.Error("Failed generating Encryption key [%s].", err.Error()) return nil, nil, nil, err } encPub, err := x509.MarshalPKIXPublicKey(&encPriv.PublicKey) if err != nil { node.log.Error("Failed marshalling Encryption key [%s].", err.Error()) return nil, nil, nil, err } req := &obcca.ECertCreateReq{&protobuf.Timestamp{Seconds: time.Now().Unix(), Nanos: 0}, &obcca.Identity{id}, &obcca.Token{Tok: []byte(pw)}, &obcca.PublicKey{obcca.CryptoType_ECDSA, signPub}, &obcca.PublicKey{obcca.CryptoType_ECDSA, encPub}, nil} resp, err := ecaP.CreateCertificatePair(context.Background(), req) if err != nil { node.log.Error("Failed invoking CreateCertficatePair [%s].", err.Error()) return nil, nil, nil, err } //out, err := rsa.DecryptPKCS1v15(rand.Reader, encPriv, resp.Tok.Tok) spi := ecies.NewSPI() eciesKey, err := spi.NewPrivateKey(nil, encPriv) if err != nil { node.log.Error("Failed parsing decrypting key [%s].", err.Error()) return nil, nil, nil, err } ecies, err := spi.NewAsymmetricCipherFromPublicKey(eciesKey) if err != nil { node.log.Error("Failed creating asymmetrinc cipher [%s].", err.Error()) return nil, nil, nil, err } out, err := ecies.Process(resp.Tok.Tok) if err != nil { node.log.Error("Failed decrypting toke [%s].", err.Error()) return nil, nil, nil, err } req.Tok.Tok = out req.Sig = nil hash := utils.NewHash() raw, _ := proto.Marshal(req) hash.Write(raw) r, s, err := ecdsa.Sign(rand.Reader, signPriv, hash.Sum(nil)) if err != nil { node.log.Error("Failed signing [%s].", err.Error()) return nil, nil, nil, err } R, _ := r.MarshalText() S, _ := s.MarshalText() req.Sig = &obcca.Signature{obcca.CryptoType_ECDSA, R, S} resp, err = ecaP.CreateCertificatePair(context.Background(), req) if err != nil { node.log.Error("Failed invoking CreateCertificatePair [%s].", err.Error()) return nil, nil, nil, err } // Verify response // Verify cert for signing node.log.Debug("Enrollment certificate for signing [%s]", utils.EncodeBase64(utils.Hash(resp.Certs.Sign))) x509SignCert, err := utils.DERToX509Certificate(resp.Certs.Sign) if err != nil { node.log.Error("Failed parsing signing enrollment certificate for signing: [%s]", err) return nil, nil, nil, err } _, err = utils.GetCriticalExtension(x509SignCert, ECertSubjectRole) if err != nil { node.log.Error("Failed parsing ECertSubjectRole in enrollment certificate for signing: [%s]", err) return nil, nil, nil, err } err = utils.CheckCertAgainstSKAndRoot(x509SignCert, signPriv, node.ecaCertPool) if err != nil { node.log.Error("Failed checking signing enrollment certificate for signing: [%s]", err) return nil, nil, nil, err } // Verify cert for encrypting node.log.Debug("Enrollment certificate for encrypting [%s]", utils.EncodeBase64(utils.Hash(resp.Certs.Enc))) x509EncCert, err := utils.DERToX509Certificate(resp.Certs.Enc) if err != nil { node.log.Error("Failed parsing signing enrollment certificate for encrypting: [%s]", err) return nil, nil, nil, err } _, err = utils.GetCriticalExtension(x509EncCert, ECertSubjectRole) if err != nil { node.log.Error("Failed parsing ECertSubjectRole in enrollment certificate for encrypting: [%s]", err) return nil, nil, nil, err } err = utils.CheckCertAgainstSKAndRoot(x509EncCert, encPriv, node.ecaCertPool) if err != nil { node.log.Error("Failed checking signing enrollment certificate for encrypting: [%s]", err) return nil, nil, nil, err } // END return signPriv, resp.Certs.Sign, resp.Chain.Tok, nil }
func (client *clientImpl) signWithTCert(tCertDER []byte, msg []byte) ([]byte, error) { // Extract the signing key from the tCert // client.node.log.Debug("TCertOwnerKDFKey [%s].", utils.EncodeBase64(client.tCertOwnerKDFKey)) TCertOwnerEncryptKey := utils.HMACTruncated(client.tCertOwnerKDFKey, []byte{1}, utils.AESKeyLength) ExpansionKey := utils.HMAC(client.tCertOwnerKDFKey, []byte{2}) tCert, err := utils.DERToX509Certificate(tCertDER) if err != nil { client.node.log.Error("Failed parsing key [%s].", err.Error()) return nil, err } // TODO: retrieve TCertIndex from the ciphertext encrypted under the TCertOwnerEncryptKey ct, err := utils.GetExtension(tCert, utils.TCertEncTCertIndex) if err != nil { client.node.log.Error("Failed getting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return nil, err } // Decrypt ct to TCertIndex (TODO: || EnrollPub_Key || EnrollID ?) decryptedTCertIndex, err := utils.CBCPKCS7Decrypt(TCertOwnerEncryptKey, ct) if err != nil { client.node.log.Error("Failed decrypting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return nil, err } // Compute ExpansionValue based on TCertIndex TCertIndex := decryptedTCertIndex client.node.log.Debug("TCertIndex [%s].", utils.EncodeBase64(TCertIndex)) mac := hmac.New(utils.NewHash, ExpansionKey) mac.Write(TCertIndex) ExpansionValue := mac.Sum(nil) // Derive tpk and tsk accordingly to ExapansionValue from enrollment pk,sk // Computable by TCA / Auditor: TCertPub_Key = EnrollPub_Key + ExpansionValue G // using elliptic curve point addition per NIST FIPS PUB 186-4- specified P-384 // Compute temporary secret key tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: client.node.enrollPrivKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(ExpansionValue) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(client.node.enrollPrivKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(client.node.enrollPrivKey.D, k) tempSK.D.Mod(tempSK.D, client.node.enrollPrivKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := client.node.enrollPrivKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( client.node.enrollPrivKey.PublicKey.X, client.node.enrollPrivKey.PublicKey.Y, tempX, tempY, ) return client.node.sign(tempSK, msg) }
func (client *clientImpl) getTCertsFromTCA(num int) ([][]byte, error) { client.node.log.Debug("Get [%d] certificates from the TCA...", num) // Contact the TCA TCertOwnerKDFKey, certDERs, err := client.callTCACreateCertificateSet(num) if err != nil { client.node.log.Debug("Failed contacting TCA [%s].", err.Error()) return nil, err } // client.node.log.Debug("TCertOwnerKDFKey [%s].", utils.EncodeBase64(TCertOwnerKDFKey)) // Store TCertOwnerKDFKey and checks that every time it is always the same key if client.tCertOwnerKDFKey != nil { // Check that the keys are the same equal := bytes.Equal(client.tCertOwnerKDFKey, TCertOwnerKDFKey) if !equal { return nil, errors.New("Failed reciving kdf key from TCA. The keys are different.") } } else { client.tCertOwnerKDFKey = TCertOwnerKDFKey // TODO: handle this situation more carefully if err := client.storeTCertOwnerKDFKey(); err != nil { client.node.log.Error("Failed storing TCertOwnerKDFKey [%s].", err.Error()) return nil, err } } // Validate the Certificates obtained TCertOwnerEncryptKey := utils.HMACTruncated(TCertOwnerKDFKey, []byte{1}, utils.AESKeyLength) ExpansionKey := utils.HMAC(TCertOwnerKDFKey, []byte{2}) resCert := make([][]byte, num) j := 0 for i := 0; i < num; i++ { client.node.log.Debug("Validating certificate [%d], [%s]", i, utils.EncodeBase64(certDERs[i])) // DER to x509 x509Cert, err := utils.DERToX509Certificate(certDERs[i]) if err != nil { client.node.log.Debug("Failed parsing certificate: [%s].", err) continue } // Handle Critical Extenstion TCertEncTCertIndex tCertIndexCT, err := utils.GetCriticalExtension(x509Cert, utils.TCertEncTCertIndex) if err != nil { client.node.log.Error("Failed getting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) continue } // Verify certificate against root if _, err := utils.CheckCertAgainRoot(x509Cert, client.node.tcaCertPool); err != nil { client.node.log.Warning("Warning verifing certificate [%s].", err.Error()) continue } // Verify public key // 384-bit ExpansionValue = HMAC(Expansion_Key, TCertIndex) // Let TCertIndex = Timestamp, RandValue, 1,2,… // Timestamp assigned, RandValue assigned and counter reinitialized to 1 per batch // Decrypt ct to TCertIndex (TODO: || EnrollPub_Key || EnrollID ?) pt, err := utils.CBCPKCS7Decrypt(TCertOwnerEncryptKey, tCertIndexCT) if err != nil { client.node.log.Error("Failed decrypting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) continue } // Compute ExpansionValue based on TCertIndex TCertIndex := pt // TCertIndex := []byte(strconv.Itoa(i)) client.node.log.Debug("TCertIndex: [%s].", utils.EncodeBase64(TCertIndex)) mac := hmac.New(utils.NewHash, ExpansionKey) mac.Write(TCertIndex) ExpansionValue := mac.Sum(nil) // Derive tpk and tsk accordingly to ExapansionValue from enrollment pk,sk // Computable by TCA / Auditor: TCertPub_Key = EnrollPub_Key + ExpansionValue G // using elliptic curve point addition per NIST FIPS PUB 186-4- specified P-384 // Compute temporary secret key tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: client.node.enrollPrivKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(ExpansionValue) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(client.node.enrollPrivKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(client.node.enrollPrivKey.D, k) tempSK.D.Mod(tempSK.D, client.node.enrollPrivKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := client.node.enrollPrivKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( client.node.enrollPrivKey.PublicKey.X, client.node.enrollPrivKey.PublicKey.Y, tempX, tempY, ) // Verify temporary public key is a valid point on the reference curve isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y) if !isOn { client.node.log.Error("Failed temporary public key IsOnCurve check.") continue } // Check that the derived public key is the same as the one in the certificate certPK := x509Cert.PublicKey.(*ecdsa.PublicKey) cmp := certPK.X.Cmp(tempSK.PublicKey.X) if cmp != 0 { client.node.log.Error("Derived public key is different on X") continue } cmp = certPK.Y.Cmp(tempSK.PublicKey.Y) if cmp != 0 { client.node.log.Error("Derived public key is different on Y") continue } // Verify the signing capability of tempSK err = utils.VerifySignCapability(tempSK, x509Cert.PublicKey) if err != nil { client.node.log.Error("Failed verifing signing capability [%s].", err.Error()) continue } // Marshall certificate and secret key to be stored in the database resCert[j] = certDERs[i] if err != nil { client.node.log.Error("Failed marshalling private key [%s].", err.Error()) continue } if err := utils.CheckCertPKAgainstSK(x509Cert, interface{}(tempSK)); err != nil { client.node.log.Error("Failed checking TCA cert PK against private key [%s].", err.Error()) continue } client.node.log.Debug("Sub index [%d]", j) j++ client.node.log.Debug("Certificate [%d] validated.", i) } if j == 0 { client.node.log.Error("No valid TCert was sent") return nil, errors.New("No valid TCert was sent.") } return resCert[:j], nil }