mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 10:37:56 +00:00 
			
		
		
		
	vault-24597: add key types and key creation for CMAC (#25967)
* add key types for cmac for transit key creation * add test for key creation * fix test logic and add cases * fix logic for hmac * add go doc * fix key size and add check for HMAC key
This commit is contained in:
		| @@ -222,6 +222,10 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d * | |||||||
| 		polReq.KeyType = keysutil.KeyType_HMAC | 		polReq.KeyType = keysutil.KeyType_HMAC | ||||||
| 	case "managed_key": | 	case "managed_key": | ||||||
| 		polReq.KeyType = keysutil.KeyType_MANAGED_KEY | 		polReq.KeyType = keysutil.KeyType_MANAGED_KEY | ||||||
|  | 	case "aes128-cmac": | ||||||
|  | 		polReq.KeyType = keysutil.KeyType_AES128_CMAC | ||||||
|  | 	case "aes256-cmac": | ||||||
|  | 		polReq.KeyType = keysutil.KeyType_AES256_CMAC | ||||||
| 	default: | 	default: | ||||||
| 		return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest | 		return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -195,3 +195,113 @@ func TestTransit_CreateKeyWithAutorotation(t *testing.T) { | |||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // TestTransit_CreateKey validates transit key creation functionality | ||||||
|  | func TestTransit_CreateKey(t *testing.T) { | ||||||
|  | 	testCases := map[string]struct { | ||||||
|  | 		creationParams map[string]interface{} | ||||||
|  | 		shouldError    bool | ||||||
|  | 	}{ | ||||||
|  | 		"AES-128": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "aes128-gcm96"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"AES-256": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "aes256-gcm96"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"CHACHA20": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "chacha20-poly1305"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"ECDSA-P256": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "ecdsa-p256"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"ECDSA-P384": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "ecdsa-p384"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"ECDSA-P521": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "ecdsa-p521"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"RSA_2048": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "rsa-2048"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"RSA_3072": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "rsa-3072"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"RSA_4096": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "rsa-4096"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"HMAC": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "hmac", "key_size": 128}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"AES-128 CMAC": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "aes128-cmac"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"AES-256 CMAC": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "aes256-cmac"}, | ||||||
|  | 			shouldError:    false, | ||||||
|  | 		}, | ||||||
|  | 		"bad key type": { | ||||||
|  | 			creationParams: map[string]interface{}{"type": "fake-key-type"}, | ||||||
|  | 			shouldError:    true, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	coreConfig := &vault.CoreConfig{ | ||||||
|  | 		LogicalBackends: map[string]logical.Factory{ | ||||||
|  | 			"transit": transit.Factory, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ | ||||||
|  | 		HandlerFunc: vaulthttp.Handler, | ||||||
|  | 	}) | ||||||
|  | 	cluster.Start() | ||||||
|  | 	defer cluster.Cleanup() | ||||||
|  | 	cores := cluster.Cores | ||||||
|  | 	vault.TestWaitActive(t, cores[0].Core) | ||||||
|  | 	client := cores[0].Client | ||||||
|  | 	err := client.Sys().Mount("transit", &api.MountInput{ | ||||||
|  | 		Type: "transit", | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for name, tt := range testCases { | ||||||
|  | 		t.Run(name, func(t *testing.T) { | ||||||
|  | 			keyName, err := uuid.GenerateUUID() | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatalf("error generating key name: %s", err) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			resp, err := client.Logical().Write(fmt.Sprintf("transit/keys/%s", keyName), tt.creationParams) | ||||||
|  | 			if err != nil && !tt.shouldError { | ||||||
|  | 				t.Fatalf("unexpected error creating key: %s", err) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if err == nil && tt.shouldError { | ||||||
|  | 				t.Fatal("expected error but got nil") | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if err == nil { | ||||||
|  | 				keyType, ok := resp.Data["type"] | ||||||
|  | 				if !ok { | ||||||
|  | 					t.Fatal("missing key type in response") | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if keyType != tt.creationParams["type"] { | ||||||
|  | 					t.Fatalf("incorrect key type: expected %s, got %s", tt.creationParams["type"], keyType) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -397,6 +397,12 @@ func (lm *LockManager) GetPolicy(ctx context.Context, req PolicyRequest, rand io | |||||||
| 				return nil, false, fmt.Errorf("key derivation and convergent encryption not supported for keys of type %v", req.KeyType) | 				return nil, false, fmt.Errorf("key derivation and convergent encryption not supported for keys of type %v", req.KeyType) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 		case KeyType_AES128_CMAC, KeyType_AES256_CMAC: | ||||||
|  | 			if req.Derived || req.Convergent { | ||||||
|  | 				cleanup() | ||||||
|  | 				return nil, false, fmt.Errorf("key derivation and convergent encryption not supported for keys of type %v", req.KeyType) | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			cleanup() | 			cleanup() | ||||||
| 			return nil, false, fmt.Errorf("unsupported key type %v", req.KeyType) | 			return nil, false, fmt.Errorf("unsupported key type %v", req.KeyType) | ||||||
|   | |||||||
| @@ -68,6 +68,8 @@ const ( | |||||||
| 	KeyType_RSA3072 | 	KeyType_RSA3072 | ||||||
| 	KeyType_MANAGED_KEY | 	KeyType_MANAGED_KEY | ||||||
| 	KeyType_HMAC | 	KeyType_HMAC | ||||||
|  | 	KeyType_AES128_CMAC | ||||||
|  | 	KeyType_AES256_CMAC | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -202,6 +204,10 @@ func (kt KeyType) String() string { | |||||||
| 		return "hmac" | 		return "hmac" | ||||||
| 	case KeyType_MANAGED_KEY: | 	case KeyType_MANAGED_KEY: | ||||||
| 		return "managed_key" | 		return "managed_key" | ||||||
|  | 	case KeyType_AES128_CMAC: | ||||||
|  | 		return "aes128-cmac" | ||||||
|  | 	case KeyType_AES256_CMAC: | ||||||
|  | 		return "aes256-cmac" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return "[unknown]" | 	return "[unknown]" | ||||||
| @@ -1611,17 +1617,20 @@ func (p *Policy) RotateInMemory(randReader io.Reader) (retErr error) { | |||||||
| 		DeprecatedCreationTime: now.Unix(), | 		DeprecatedCreationTime: now.Unix(), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader) | 	if p.Type != KeyType_AES128_CMAC && p.Type != KeyType_AES256_CMAC && p.Type != KeyType_HMAC { | ||||||
| 	if err != nil { | 		hmacKey, err := uuid.GenerateRandomBytesWithReader(32, randReader) | ||||||
| 		return err | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		entry.HMACKey = hmacKey | ||||||
| 	} | 	} | ||||||
| 	entry.HMACKey = hmacKey |  | ||||||
|  |  | ||||||
|  | 	var err error | ||||||
| 	switch p.Type { | 	switch p.Type { | ||||||
| 	case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_HMAC: | 	case KeyType_AES128_GCM96, KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_HMAC, KeyType_AES128_CMAC, KeyType_AES256_CMAC: | ||||||
| 		// Default to 256 bit key | 		// Default to 256 bit key | ||||||
| 		numBytes := 32 | 		numBytes := 32 | ||||||
| 		if p.Type == KeyType_AES128_GCM96 { | 		if p.Type == KeyType_AES128_GCM96 || p.Type == KeyType_AES128_CMAC { | ||||||
| 			numBytes = 16 | 			numBytes = 16 | ||||||
| 		} else if p.Type == KeyType_HMAC { | 		} else if p.Type == KeyType_HMAC { | ||||||
| 			numBytes = p.KeySize | 			numBytes = p.KeySize | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Rachel Culpepper
					Rachel Culpepper