1 /* SPDX-License-Identifier: GPL-2.0-or-later
2 * Copyright (C) 2023 Eneas Ulir de Queiroz
11 #include <mbedtls/cipher.h>
13 int do_crypt(FILE *infile
, FILE *outfile
, const mbedtls_cipher_info_t
*cipher_info
,
14 const unsigned char *key
, const unsigned char *iv
, int enc
, int padding
)
16 mbedtls_cipher_context_t ctx
;
17 unsigned char inbuf
[1024], outbuf
[1024 + MBEDTLS_MAX_BLOCK_LENGTH
];
22 mbedtls_cipher_init(&ctx
);
23 if ((ret
= mbedtls_cipher_setup(&ctx
, cipher_info
))) {
24 fprintf(stderr
, "Error: mbedtls_cipher_setup: %d\n", ret
);
27 step
= iv
? 1024 : mbedtls_cipher_get_block_size(&ctx
);
28 if ((ret
= mbedtls_cipher_setkey(&ctx
, key
, (int) mbedtls_cipher_get_key_bitlen(&ctx
),
29 enc
? MBEDTLS_ENCRYPT
: MBEDTLS_DECRYPT
))) {
30 fprintf(stderr
, "Error: mbedtls_cipher_setkey: %d\n", ret
);
33 if (iv
&& (ret
= mbedtls_cipher_set_iv(&ctx
, iv
, cipher_info
->iv_size
))) {
34 fprintf(stderr
, "Error: mbedtls_cipher_set_iv: %d\n", ret
);
38 if (cipher_info
->block_size
> 1) {
39 if (cipher_info
->mode
== MBEDTLS_MODE_CBC
) {
40 if ((ret
= mbedtls_cipher_set_padding_mode(&ctx
,
41 padding
? MBEDTLS_PADDING_PKCS7
42 : MBEDTLS_PADDING_NONE
))) {
43 fprintf(stderr
, "Error: mbedtls_cipher_set_padding_mode: %d\n", ret
);
47 if (cipher_info
->mode
!= MBEDTLS_MODE_CBC
&& padding
) {
48 fprintf(stderr
, "Error: mbedTLS only supports padding with CBC ciphers.\n");
54 if ((ret
= mbedtls_cipher_reset(&ctx
))) {
55 fprintf(stderr
, "Error: mbedtls_cipher_reset: %d\n", ret
);
60 inlen
= fread(inbuf
, 1, step
, infile
);
63 if ((ret
= mbedtls_cipher_update(&ctx
, inbuf
, inlen
, outbuf
, &outlen
))) {
64 fprintf(stderr
, "Error: mbedtls_cipher_update: %d\n", ret
);
67 fwrite(outbuf
, 1, outlen
, outfile
);
69 if ((ret
= mbedtls_cipher_finish(&ctx
, outbuf
, &outlen
))) {
70 fprintf(stderr
, "Error: mbedtls_cipher_finish: %d\n", ret
);
73 fwrite(outbuf
, 1, outlen
, outfile
);
76 mbedtls_cipher_free(&ctx
);
80 static void check_enc_dec(const int enc
)
84 fprintf(stderr
, "Error: both -d and -e were specified.\n");
88 static void check_cipher(const mbedtls_cipher_info_t
*cipher_info
)
92 if (cipher_info
== NULL
) {
93 fprintf(stderr
, "Error: invalid cipher: %s.\n", optarg
);
94 fprintf(stderr
, "Supported ciphers: \n");
95 for (list
= mbedtls_cipher_list(); *list
; list
++) {
96 cipher_info
= mbedtls_cipher_info_from_type(*list
);
99 fprintf(stderr
, "\t%s\n", cipher_info
->name
);
105 static void show_usage(const char* name
)
107 fprintf(stderr
, "Usage: %s: [-d | -e] [-n] -k key [-i iv] [-c cipher]\n"
108 "-d = decrypt; -e = encrypt; -n = no padding\n", name
);
111 char *hexstr2buf(const char *str
, size_t *len
)
114 size_t inlen
= strlen(str
);
122 for (size_t x
= 0; x
< *len
; x
++)
123 sscanf(str
+ x
* 2, "%2hhx", buf
+ x
);
127 static char* upperstr(char *str
) {
128 for (char *s
= str
; *s
; s
++)
129 *s
= toupper((unsigned char) *s
);
133 int main(int argc
, char *argv
[])
136 unsigned char *iv
= NULL
;
137 unsigned char *key
= NULL
;
138 size_t keylen
= 0, ivlen
= 0;
141 const mbedtls_cipher_info_t
*cipher_info
=
142 mbedtls_cipher_info_from_type (MBEDTLS_CIPHER_AES_128_CBC
);
145 while ((opt
= getopt(argc
, argv
, "c:dei:k:n")) != -1) {
148 cipher_info
= mbedtls_cipher_info_from_string(upperstr(optarg
));
149 check_cipher(cipher_info
);
160 iv
= (unsigned char *) hexstr2buf((const char *)optarg
, &ivlen
);
162 fprintf(stderr
, "Error setting IV to %s. The IV should be encoded in hex.\n",
168 key
= (unsigned char *) hexstr2buf((const char *)optarg
, &keylen
);
170 fprintf(stderr
, "Error setting key to %s. The key should be encoded in hex.\n",
183 if (cipher_info
->iv_size
) {
185 fprintf(stderr
, "Error: iv not set.\n");
189 if (ivlen
!= cipher_info
->iv_size
) {
190 fprintf(stderr
, "Error: IV must be %d bytes; given IV is %zd bytes.\n",
191 cipher_info
->iv_size
, ivlen
);
196 fprintf(stderr
, "Error: key not set.\n");
200 if (keylen
!= cipher_info
->key_bitlen
>> 3) {
201 fprintf(stderr
, "Error: key must be %d bytes; given key is %zd bytes.\n",
202 cipher_info
->key_bitlen
>> 3, keylen
);
205 ret
= do_crypt(stdin
, stdout
, cipher_info
, key
, iv
, !!enc
, padding
);
207 memset(iv
, 0, ivlen
);
208 memset(key
, 0, keylen
);