github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/value/encryption/dae/builders.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package dae
    19  
    20  import (
    21  	"crypto/aes"
    22  	"crypto/cipher"
    23  	"crypto/sha256"
    24  	"fmt"
    25  	"strings"
    26  
    27  	miscreant "github.com/miscreant/miscreant.go"
    28  
    29  	"github.com/zntrio/harp/v2/build/fips"
    30  	"github.com/zntrio/harp/v2/pkg/sdk/value"
    31  	"github.com/zntrio/harp/v2/pkg/sdk/value/encryption"
    32  
    33  	"golang.org/x/crypto/chacha20poly1305"
    34  )
    35  
    36  var (
    37  	aesgcmPrefix     = "dae-aes-gcm"
    38  	aespmacsivPrefix = "dae-aes-pmac-siv"
    39  	aessivPrefix     = "dae-aes-siv"
    40  	chachaPrefix     = "dae-chacha"
    41  	xchachaPrefix    = "dae-xchacha"
    42  )
    43  
    44  func init() {
    45  	encryption.Register(aesgcmPrefix, AESGCM)
    46  
    47  	if !fips.Enabled() {
    48  		encryption.Register(aespmacsivPrefix, AESPMACSIV)
    49  		encryption.Register(aessivPrefix, AESSIV)
    50  		encryption.Register(chachaPrefix, Chacha20Poly1305)
    51  		encryption.Register(xchachaPrefix, XChacha20Poly1305)
    52  	}
    53  }
    54  
    55  // AESGCM returns an AES-GCM value transformer instance.
    56  func AESGCM(key string) (value.Transformer, error) {
    57  	// Remove the prefix
    58  	key = strings.TrimPrefix(key, "dae-aes-gcm:")
    59  
    60  	k, salt, err := decodeKey(key)
    61  	if err != nil {
    62  		return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err)
    63  	}
    64  	switch len(k) {
    65  	case 16, 24, 32:
    66  	default:
    67  		return nil, fmt.Errorf("aes: invalid key length, use 16 bytes (AES128) or 24 bytes (AES192) or 32 bytes (AES256)")
    68  	}
    69  
    70  	// Derive keys from input key
    71  	dk, err := deriveKey(k, salt, nil, len(k)+32)
    72  	if err != nil {
    73  		return nil, fmt.Errorf("aes: unable te derive required keys: %w", err)
    74  	}
    75  
    76  	// Create AES block cipher
    77  	block, err := aes.NewCipher(dk[:len(k)])
    78  	if err != nil {
    79  		return nil, fmt.Errorf("aes: unable to initialize block cipher: %w", err)
    80  	}
    81  
    82  	// Initialize AEAD cipher chain
    83  	aead, err := cipher.NewGCM(block)
    84  	if err != nil {
    85  		return nil, fmt.Errorf("aes: unable to initialize aead chain : %w", err)
    86  	}
    87  
    88  	// Return transformer
    89  	return &daeTransformer{
    90  		aead:             aead,
    91  		nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]),
    92  	}, nil
    93  }
    94  
    95  // AESSIV returns an AES-SIV/AES-CMAC-SIV value transformer instance.
    96  func AESSIV(key string) (value.Transformer, error) {
    97  	// Remove the prefix
    98  	key = strings.TrimPrefix(key, "dae-aes-siv:")
    99  
   100  	// Decode key
   101  	k, salt, err := decodeKey(key)
   102  	if err != nil {
   103  		return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err)
   104  	}
   105  	if l := len(k); l != 64 {
   106  		return nil, fmt.Errorf("aes: invalid secret key length (%d)", l)
   107  	}
   108  
   109  	// Derive keys from input key
   110  	dk, err := deriveKey(k, salt, nil, len(k)+32)
   111  	if err != nil {
   112  		return nil, fmt.Errorf("aes: unable te derive required keys: %w", err)
   113  	}
   114  
   115  	// Initialize AEAD
   116  	aead, err := miscreant.NewAEAD("AES-SIV", dk[:len(k)], 32)
   117  	if err != nil {
   118  		return nil, fmt.Errorf("aes: unable to initialize aes-pmac-siv: %w", err)
   119  	}
   120  
   121  	// Return transformer
   122  	return &daeTransformer{
   123  		aead:             aead,
   124  		nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]),
   125  	}, nil
   126  }
   127  
   128  // AESPMACSIV returns an AES-PMAC-SIV value transformer instance.
   129  func AESPMACSIV(key string) (value.Transformer, error) {
   130  	// Remove the prefix
   131  	key = strings.TrimPrefix(key, "dae-aes-pmac-siv:")
   132  
   133  	// Decode key
   134  	k, salt, err := decodeKey(key)
   135  	if err != nil {
   136  		return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err)
   137  	}
   138  	if l := len(k); l != 64 {
   139  		return nil, fmt.Errorf("aes: invalid secret key length (%d)", l)
   140  	}
   141  
   142  	// Derive keys from input key
   143  	dk, err := deriveKey(k, salt, nil, len(k)+32)
   144  	if err != nil {
   145  		return nil, fmt.Errorf("aes: unable te derive required keys: %w", err)
   146  	}
   147  
   148  	// Initialize AEAD
   149  	aead, err := miscreant.NewAEAD("AES-PMAC-SIV", dk[:len(k)], 32)
   150  	if err != nil {
   151  		return nil, fmt.Errorf("aes: unable to initialize aes-pmac-siv: %w", err)
   152  	}
   153  
   154  	// Return transformer
   155  	return &daeTransformer{
   156  		aead:             aead,
   157  		nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]),
   158  	}, nil
   159  }
   160  
   161  // Chacha20Poly1305 returns an ChaCha20Poly1305 value transformer instance.
   162  func Chacha20Poly1305(key string) (value.Transformer, error) {
   163  	// Remove the prefix
   164  	key = strings.TrimPrefix(key, "dae-chacha:")
   165  
   166  	// Decode key
   167  	k, salt, err := decodeKey(key)
   168  	if err != nil {
   169  		return nil, fmt.Errorf("chacha: unable to decode transformer key: %w", err)
   170  	}
   171  	if l := len(k); l != 32 {
   172  		return nil, fmt.Errorf("chacha: invalid secret key length (%d)", l)
   173  	}
   174  
   175  	// Derive keys from input key
   176  	dk, err := deriveKey(k, salt, nil, len(k)+32)
   177  	if err != nil {
   178  		return nil, fmt.Errorf("chacha: unable te derive required keys: %w", err)
   179  	}
   180  
   181  	// Create Chacha20-Poly1305 aead cipher
   182  	aead, err := chacha20poly1305.New(dk[:len(k)])
   183  	if err != nil {
   184  		return nil, fmt.Errorf("chacha: unable to initialize chacha cipher: %w", err)
   185  	}
   186  
   187  	// Return transformer
   188  	return &daeTransformer{
   189  		aead:             aead,
   190  		nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]),
   191  	}, nil
   192  }
   193  
   194  // XChacha20Poly1305 returns an XChaCha20Poly1305 value transformer instance.
   195  func XChacha20Poly1305(key string) (value.Transformer, error) {
   196  	// Remove the prefix
   197  	key = strings.TrimPrefix(key, "dae-xchacha:")
   198  
   199  	// Decode key
   200  	k, salt, err := decodeKey(key)
   201  	if err != nil {
   202  		return nil, fmt.Errorf("xchacha: unable to decode transformer key: %w", err)
   203  	}
   204  	if l := len(k); l != 32 {
   205  		return nil, fmt.Errorf("xchacha: invalid secret key length (%d)", l)
   206  	}
   207  
   208  	// Derive keys from input key
   209  	dk, err := deriveKey(k, salt, nil, len(k)+32)
   210  	if err != nil {
   211  		return nil, fmt.Errorf("xchacha: unable te derive required keys: %w", err)
   212  	}
   213  
   214  	// Create Chacha20-Poly1305 aead cipher
   215  	aead, err := chacha20poly1305.NewX(dk[:len(k)])
   216  	if err != nil {
   217  		return nil, fmt.Errorf("xchacha: unable to initialize chacha cipher: %w", err)
   218  	}
   219  
   220  	// Return transformer
   221  	return &daeTransformer{
   222  		aead:             aead,
   223  		nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]),
   224  	}, nil
   225  }