func (validator *validatorImpl) deepCloneAndDecryptTx1_1(tx *obc.Transaction) (*obc.Transaction, error) { if tx.Nonce == nil || len(tx.Nonce) == 0 { return nil, errors.New("Failed decrypting payload. Invalid nonce.") } // clone tx clone, err := validator.deepCloneTransaction(tx) if err != nil { validator.error("Failed deep cloning [%s].", err.Error()) return nil, err } // Derive root key // client.enrollChainKey is an AES key represented as byte array enrollChainKey := validator.enrollChainKey.([]byte) key := utils.HMAC(enrollChainKey, clone.Nonce) // validator.log.Info("Deriving from ", utils.EncodeBase64(validator.peer.node.enrollChainKey)) // validator.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // validator.log.Info("Derived key ", utils.EncodeBase64(key)) // validator.log.Info("Encrypted Payload ", utils.EncodeBase64(tx.EncryptedPayload)) // validator.log.Info("Encrypted ChaincodeID ", utils.EncodeBase64(tx.EncryptedChaincodeID)) // Decrypt Payload payloadKey := utils.HMACTruncated(key, []byte{1}, utils.AESKeyLength) payload, err := utils.CBCPKCS7Decrypt(payloadKey, utils.Clone(clone.Payload)) if err != nil { validator.error("Failed decrypting payload [%s].", err.Error()) return nil, err } clone.Payload = payload // Decrypt ChaincodeID chaincodeIDKey := utils.HMACTruncated(key, []byte{2}, utils.AESKeyLength) chaincodeID, err := utils.CBCPKCS7Decrypt(chaincodeIDKey, utils.Clone(clone.ChaincodeID)) if err != nil { validator.error("Failed decrypting chaincode [%s].", err.Error()) return nil, err } clone.ChaincodeID = chaincodeID // Decrypt metadata if len(clone.Metadata) != 0 { metadataKey := utils.HMACTruncated(key, []byte{3}, utils.AESKeyLength) metadata, err := utils.CBCPKCS7Decrypt(metadataKey, utils.Clone(clone.Metadata)) if err != nil { validator.error("Failed decrypting metadata [%s].", err.Error()) return nil, err } clone.Metadata = metadata } return clone, nil }
func (validator *validatorImpl) decryptTx(tx *obc.Transaction) (*obc.Transaction, error) { if tx.Nonce == nil || len(tx.Nonce) == 0 { return nil, errors.New("Failed decrypting payload. Invalid nonce.") } // clone tx clone, err := validator.deepCloneTransaction(tx) if err != nil { validator.peer.node.log.Error("Failed deep cloning [%s].", err.Error()) return nil, err } // Derive root key key := utils.HMAC(validator.peer.node.enrollChainKey, clone.Nonce) // validator.peer.node.log.Info("Deriving from ", utils.EncodeBase64(validator.peer.node.enrollChainKey)) // validator.peer.node.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // validator.peer.node.log.Info("Derived key ", utils.EncodeBase64(key)) // validator.peer.node.log.Info("Encrypted Payload ", utils.EncodeBase64(tx.EncryptedPayload)) // validator.peer.node.log.Info("Encrypted ChaincodeID ", utils.EncodeBase64(tx.EncryptedChaincodeID)) // Decrypt using the derived key payloadKey := utils.HMACTruncated(key, []byte{1}, utils.AESKeyLength) encryptedPayload := make([]byte, len(clone.EncryptedPayload)) copy(encryptedPayload, clone.EncryptedPayload) payload, err := utils.CBCPKCS7Decrypt(payloadKey, encryptedPayload) if err != nil { validator.peer.node.log.Error("Failed decrypting payload [%s].", err.Error()) return nil, err } clone.Payload = payload chaincodeIDKey := utils.HMACTruncated(key, []byte{2}, utils.AESKeyLength) encryptedChaincodeID := make([]byte, len(clone.EncryptedChaincodeID)) copy(encryptedChaincodeID, clone.EncryptedChaincodeID) rawChaincodeID, err := utils.CBCPKCS7Decrypt(chaincodeIDKey, encryptedChaincodeID) chaincodeID := &obc.ChaincodeID{} if err := proto.Unmarshal(rawChaincodeID, chaincodeID); err != nil { validator.peer.node.log.Error("Failed decrypting chaincodeID [%s].", err.Error()) return nil, err } clone.ChaincodeID = chaincodeID return clone, nil }
func (se *queryStateEncryptor) Decrypt(raw []byte) ([]byte, error) { if len(raw) <= utils.NonceSize { return nil, utils.ErrDecrypt } // raw consists of (txNonce, ct) txNonce := raw[:utils.NonceSize] // se.log.Info("Decrypting with txNonce ", utils.EncodeBase64(txNonce)) ct := raw[utils.NonceSize:] nonce := make([]byte, se.nonceSize) copy(nonce, ct) key := utils.HMACTruncated(se.deployTxKey, append([]byte{3}, txNonce...), utils.AESKeyLength) // se.log.Info("Decrypting with key ", utils.EncodeBase64(key)) c, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(c) if err != nil { return nil, err } se.nonceSize = se.gcmEnc.NonceSize() out, err := gcm.Open(nil, nonce, ct[se.nonceSize:], txNonce) if err != nil { return nil, utils.ErrDecrypt } return out, nil }
func (client *clientImpl) DecryptQueryResult(queryTx *obc.Transaction, ct []byte) ([]byte, error) { queryKey := utils.HMACTruncated(client.node.enrollChainKey, append([]byte{6}, queryTx.Nonce...), utils.AESKeyLength) // client.node.log.Info("QUERY Decrypting with key: ", utils.EncodeBase64(queryKey)) if len(ct) <= utils.NonceSize { return nil, utils.ErrDecrypt } c, err := aes.NewCipher(queryKey) if err != nil { return nil, err } gcm, err := cipher.NewGCM(c) if err != nil { return nil, err } nonce := make([]byte, gcm.NonceSize()) copy(nonce, ct) out, err := gcm.Open(nil, nonce, ct[gcm.NonceSize():], nil) if err != nil { client.node.log.Error("Failed decrypting query result [%s].", err.Error()) return nil, utils.ErrDecrypt } return out, nil }
func (client *clientImpl) encryptTx(tx *obc.Transaction) error { if len(tx.Nonce) == 0 { return errors.New("Failed encrypting payload. Invalid nonce.") } // Derive key txKey := utils.HMAC(client.node.enrollChainKey, tx.Nonce) // client.node.log.Info("Deriving from :", utils.EncodeBase64(client.node.enrollChainKey)) // client.node.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // client.node.log.Info("Derived key ", utils.EncodeBase64(txKey)) // Encrypt Payload payloadKey := utils.HMACTruncated(txKey, []byte{1}, utils.AESKeyLength) encryptedPayload, err := utils.CBCPKCS7Encrypt(payloadKey, tx.Payload) if err != nil { return err } tx.Payload = encryptedPayload // Encrypt ChaincodeID chaincodeIDKey := utils.HMACTruncated(txKey, []byte{2}, utils.AESKeyLength) encryptedChaincodeID, err := utils.CBCPKCS7Encrypt(chaincodeIDKey, tx.ChaincodeID) if err != nil { return err } tx.ChaincodeID = encryptedChaincodeID // Encrypt Metadata if len(tx.Metadata) != 0 { metadataKey := utils.HMACTruncated(txKey, []byte{3}, utils.AESKeyLength) encryptedMetadata, err := utils.CBCPKCS7Encrypt(metadataKey, tx.Metadata) if err != nil { return err } tx.Metadata = encryptedMetadata } client.node.log.Debug("Encrypted ChaincodeID [%s].", utils.EncodeBase64(tx.ChaincodeID)) client.node.log.Debug("Encrypted Payload [%s].", utils.EncodeBase64(tx.Payload)) client.node.log.Debug("Encrypted Metadata [%s].", utils.EncodeBase64(tx.Metadata)) return nil }
// DecryptQueryResult is used to decrypt the result of a query transaction func (client *clientImpl) DecryptQueryResult(queryTx *obc.Transaction, ct []byte) ([]byte, error) { // Verify that the client is initialized if !client.isInitialized { return nil, utils.ErrNotInitialized } var queryKey []byte switch queryTx.ConfidentialityProtocolVersion { case "1.1": enrollChainKey := client.enrollChainKey.([]byte) queryKey = utils.HMACTruncated(enrollChainKey, append([]byte{6}, queryTx.Nonce...), utils.AESKeyLength) // client.log.Info("QUERY Decrypting with key: ", utils.EncodeBase64(queryKey)) break case "1.2": queryKey = utils.HMACTruncated(client.queryStateKey, append([]byte{6}, queryTx.Nonce...), utils.AESKeyLength) } if len(ct) <= utils.NonceSize { return nil, utils.ErrDecrypt } c, err := aes.NewCipher(queryKey) if err != nil { return nil, err } gcm, err := cipher.NewGCM(c) if err != nil { return nil, err } nonce := make([]byte, gcm.NonceSize()) copy(nonce, ct) out, err := gcm.Open(nil, nonce, ct[gcm.NonceSize():], nil) if err != nil { client.error("Failed decrypting query result [%s].", err.Error()) return nil, utils.ErrDecrypt } return out, nil }
func (client *clientImpl) encryptTxVersion1_1(tx *obc.Transaction) error { // client.enrollChainKey is an AES key represented as byte array enrollChainKey := client.enrollChainKey.([]byte) // Derive key txKey := utils.HMAC(enrollChainKey, tx.Nonce) // client.log.Info("Deriving from :", utils.EncodeBase64(client.node.enrollChainKey)) // client.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // client.log.Info("Derived key ", utils.EncodeBase64(txKey)) // Encrypt Payload payloadKey := utils.HMACTruncated(txKey, []byte{1}, utils.AESKeyLength) encryptedPayload, err := utils.CBCPKCS7Encrypt(payloadKey, tx.Payload) if err != nil { return err } tx.Payload = encryptedPayload // Encrypt ChaincodeID chaincodeIDKey := utils.HMACTruncated(txKey, []byte{2}, utils.AESKeyLength) encryptedChaincodeID, err := utils.CBCPKCS7Encrypt(chaincodeIDKey, tx.ChaincodeID) if err != nil { return err } tx.ChaincodeID = encryptedChaincodeID // Encrypt Metadata if len(tx.Metadata) != 0 { metadataKey := utils.HMACTruncated(txKey, []byte{3}, utils.AESKeyLength) encryptedMetadata, err := utils.CBCPKCS7Encrypt(metadataKey, tx.Metadata) if err != nil { return err } tx.Metadata = encryptedMetadata } return nil }
func (client *clientImpl) encryptTx(tx *obc.Transaction) error { if tx.Nonce == nil || len(tx.Nonce) == 0 { return errors.New("Failed encrypting payload. Invalid nonce.") } // Derive key txKey := utils.HMAC(client.node.enrollChainKey, tx.Nonce) // client.node.log.Info("Deriving from :", utils.EncodeBase64(client.node.enrollChainKey)) // client.node.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // client.node.log.Info("Derived key ", utils.EncodeBase64(txKey)) // Encrypt using the derived key payloadKey := utils.HMACTruncated(txKey, []byte{1}, utils.AESKeyLength) encryptedPayload, err := utils.CBCPKCS7Encrypt(payloadKey, tx.Payload) if err != nil { return err } tx.EncryptedPayload = encryptedPayload tx.Payload = nil chaincodeIDKey := utils.HMACTruncated(txKey, []byte{2}, utils.AESKeyLength) rawChaincodeID, err := proto.Marshal(tx.ChaincodeID) if err != nil { return err } tx.EncryptedChaincodeID, err = utils.CBCPKCS7Encrypt(chaincodeIDKey, rawChaincodeID) if err != nil { return err } tx.ChaincodeID = nil client.node.log.Debug("Encrypted Payload [%s].", utils.EncodeBase64(tx.EncryptedPayload)) client.node.log.Debug("Encrypted ChaincodeID [%s].", utils.EncodeBase64(tx.EncryptedChaincodeID)) return nil }
func (se *stateEncryptorImpl) Encrypt(msg []byte) ([]byte, error) { var b = make([]byte, 8) binary.BigEndian.PutUint64(b, se.counter) se.log.Debug("Encrypting with counter [%s].", utils.EncodeBase64(b)) // se.log.Info("Encrypting with txNonce ", utils.EncodeBase64(se.txNonce)) nonce := utils.HMACTruncated(se.nonceStateKey, b, se.nonceSize) se.counter++ // Seal will append the output to the first argument; the usage // here appends the ciphertext to the nonce. The final parameter // is any additional data to be authenticated. out := se.gcmEnc.Seal(nonce, nonce, msg, se.invokeTxNonce) return append(se.invokeTxNonce, out...), nil }
func (validator *validatorImpl) GetStateEncryptor(deployTx, executeTx *obc.Transaction) (StateEncryptor, error) { // Check nonce if deployTx.Nonce == nil || len(deployTx.Nonce) == 0 { return nil, errors.New("Invalid deploy nonce.") } if executeTx.Nonce == nil || len(executeTx.Nonce) == 0 { return nil, errors.New("Invalid invoke nonce.") } // Check ChaincodeID if deployTx.ChaincodeID == nil { return nil, errors.New("Invalid deploy chaincodeID.") } if executeTx.ChaincodeID == nil { return nil, errors.New("Invalid execute chaincodeID.") } // Check that deployTx and executeTx refers to the same chaincode if !reflect.DeepEqual(deployTx.ChaincodeID, executeTx.ChaincodeID) { return nil, utils.ErrDirrentChaincodeID } validator.peer.node.log.Debug("Parsing transaction. Type [%s].", executeTx.Type.String()) if executeTx.Type == obc.Transaction_CHAINCODE_QUERY { validator.peer.node.log.Debug("Parsing Query transaction...") // Compute deployTxKey key from the deploy transaction. This is used to decrypt the actual state // of the chaincode deployTxKey := utils.HMAC(validator.peer.node.enrollChainKey, deployTx.Nonce) // Compute the key used to encrypt the result of the query queryKey := utils.HMACTruncated(validator.peer.node.enrollChainKey, append([]byte{6}, executeTx.Nonce...), utils.AESKeyLength) // Init the state encryptor se := queryStateEncryptor{} err := se.init(validator.peer.node.log, queryKey, deployTxKey) if err != nil { return nil, err } return &se, nil } // Compute deployTxKey key from the deploy transaction deployTxKey := utils.HMAC(validator.peer.node.enrollChainKey, deployTx.Nonce) // Mask executeTx.Nonce executeTxNonce := utils.HMACTruncated(deployTxKey, utils.Hash(executeTx.Nonce), utils.NonceSize) // Compute stateKey to encrypt the states and nonceStateKey to generates IVs. This // allows validators to reach consesus stateKey := utils.HMACTruncated(deployTxKey, append([]byte{3}, executeTxNonce...), utils.AESKeyLength) nonceStateKey := utils.HMAC(deployTxKey, append([]byte{4}, executeTxNonce...)) // Init the state encryptor se := stateEncryptorImpl{} err := se.init(validator.peer.node.log, stateKey, nonceStateKey, deployTxKey, executeTxNonce) if err != nil { return nil, err } return &se, nil }
func (client *clientImpl) encryptTxVersion1_2(tx *obc.Transaction) error { // Create (PK_C,SK_C) pair ccPrivateKey, err := client.eciesSPI.NewPrivateKey(rand.Reader, conf.GetDefaultCurve()) if err != nil { client.error("Failed generate chaincode keypair: [%s]", err) return err } // Prepare message to the validators var ( stateKey []byte privBytes []byte ) switch tx.Type { case obc.Transaction_CHAINCODE_NEW: // Prepare chaincode stateKey and privateKey stateKey, err = utils.GenAESKey() if err != nil { client.error("Failed creating state key: [%s]", err) return err } privBytes, err = client.eciesSPI.SerializePrivateKey(ccPrivateKey) if err != nil { client.error("Failed serializing chaincode key: [%s]", err) return err } break case obc.Transaction_CHAINCODE_QUERY: // Prepare chaincode stateKey and privateKey stateKey = utils.HMACTruncated(client.queryStateKey, append([]byte{6}, tx.Nonce...), utils.AESKeyLength) privBytes, err = client.eciesSPI.SerializePrivateKey(ccPrivateKey) if err != nil { client.error("Failed serializing chaincode key: [%s]", err) return err } break case obc.Transaction_CHAINCODE_EXECUTE: // Prepare chaincode stateKey and privateKey stateKey = make([]byte, 0) privBytes, err = client.eciesSPI.SerializePrivateKey(ccPrivateKey) if err != nil { client.error("Failed serializing chaincode key: [%s]", err) return err } break } // Encrypt message to the validators cipher, err := client.eciesSPI.NewAsymmetricCipherFromPublicKey(client.chainPublicKey) if err != nil { client.error("Failed creating new encryption scheme: [%s]", err) return err } msgToValidators, err := asn1.Marshal(chainCodeValidatorMessage1_2{privBytes, stateKey}) if err != nil { client.error("Failed preparing message to the validators: [%s]", err) return err } encMsgToValidators, err := cipher.Process(msgToValidators) if err != nil { client.error("Failed encrypting message to the validators: [%s]", err) return err } tx.ToValidators = encMsgToValidators // Encrypt the rest of the fields // Init with chainccode pk cipher, err = client.eciesSPI.NewAsymmetricCipherFromPublicKey(ccPrivateKey.GetPublicKey()) if err != nil { client.error("Failed initiliazing encryption scheme: [%s]", err) return err } // Encrypt chaincodeID using pkC encryptedChaincodeID, err := cipher.Process(tx.ChaincodeID) if err != nil { client.error("Failed encrypting chaincodeID: [%s]", err) return err } tx.ChaincodeID = encryptedChaincodeID // Encrypt payload using pkC encryptedPayload, err := cipher.Process(tx.Payload) if err != nil { client.error("Failed encrypting payload: [%s]", err) return err } tx.Payload = encryptedPayload // Encrypt metadata using pkC if len(tx.Metadata) != 0 { encryptedMetadata, err := cipher.Process(tx.Metadata) if err != nil { client.error("Failed encrypting metadata: [%s]", err) return err } tx.Metadata = encryptedMetadata } return nil }
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 }
func (client *clientImpl) signUsingTCertX509(tCert *x509.Certificate, msg []byte) ([]byte, error) { // Extract the signing key from the tCert TCertOwnerEncryptKey := utils.HMACTruncated(client.tCertOwnerKDFKey, []byte{1}, utils.AESKeyLength) ExpansionKey := utils.HMAC(client.tCertOwnerKDFKey, []byte{2}) // TODO: retrieve TCertIndex from the ciphertext encrypted under the TCertOwnerEncryptKey ct, err := utils.GetCriticalExtension(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) 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 }