]>
git.wh0rd.org - dump.git/blob - rmt/cipher.c
10 #include <openssl/evp.h>
13 * Encrypt or decrypt buf, returning a pointer to the transformed data,
15 * The returned data is the same size as the input data,
16 * which means we must turn off cipher padding, and require that buflen
17 * be a multiple of the cipher block size (8 for Blowfish).
18 * To keep things simple, the return value is a malloc'd
19 * buffer that is overwritten on each call.
21 * Ken Lalonde <ken@globalremit.com>, 2003
24 cipher(char *buf
, int buflen
, int do_encrypt
)
26 static EVP_CIPHER_CTX ctx
;
27 static char *out
= NULL
; /* return value, grown as necessary */
28 static int outlen
= 0;
29 static int init
= 0, which
, blocksize
;
33 static const EVP_CIPHER
*cipher
;
34 unsigned char key
[EVP_MAX_KEY_LENGTH
], iv
[EVP_MAX_IV_LENGTH
];
35 // Read key from $HOME/.ermt.key
36 char *keyfile
= ".ermt.key";
37 unsigned char buf
[128];
41 openlog("ermt", LOG_PID
, LOG_DAEMON
);
42 // Not needed: OpenSSL_add_all_algorithms();
43 // Not needed: ERR_load_crypto_strings();
44 cipher
= EVP_bf_cbc(); // or: EVP_aes_{128,192,256}_cbc()
45 // We want the ability to decrypt the output
46 // using "openssl enc -d -kfile K -nopad -nosalt", which
47 // means we must read the key file the same way
48 // openssl does. But be careful: if the key contains
49 // \0 or \r or \n, the effective size will be reduced.
50 if ((fp
= fopen(keyfile
, "r")) == NULL
) {
51 syslog(LOG_ERR
, "Can't open key file %s: %m", keyfile
);
55 if (!fgets(buf
, sizeof buf
, fp
)) {
56 syslog(LOG_ERR
, "Error reading key file %s: %m", keyfile
);
62 ((buf
[i
-1] == '\n') || (buf
[i
-1] == '\r')))
65 ((buf
[i
-1] == '\n') || (buf
[i
-1] == '\r')))
68 syslog(LOG_ERR
, "zero length key");
72 EVP_BytesToKey(cipher
, EVP_md5(), NULL
,
73 buf
, strlen(buf
), 1, key
, iv
);
74 EVP_CIPHER_CTX_init(&ctx
);
75 EVP_CipherInit_ex(&ctx
, cipher
, NULL
, key
, iv
, do_encrypt
);
76 EVP_CIPHER_CTX_set_padding(&ctx
, 0); // -nopad
77 OPENSSL_cleanse(buf
, sizeof buf
);
78 OPENSSL_cleanse(key
, sizeof key
);
79 OPENSSL_cleanse(iv
, sizeof iv
);
80 blocksize
= EVP_CIPHER_CTX_block_size(&ctx
);
84 if (which
!= do_encrypt
) {
85 syslog(LOG_ERR
, "Cannot switch modes");
89 if ((buflen
% blocksize
) != 0) {
90 syslog(LOG_ERR
, "Buffer size is not a multiple of cipher block size");
94 if (outlen
< buflen
+blocksize
) {
95 outlen
= (buflen
+blocksize
) * 2;
96 out
= realloc(out
, outlen
);
98 if (!EVP_CipherUpdate(&ctx
, out
, &n
, buf
, buflen
)) {
99 syslog(LOG_ERR
, "EVP_CipherUpdate failed");
104 syslog(LOG_ERR
, "EVP_CipherUpdate: %d != %d", n
, buflen
);
108 // assert(ctx->buf_len == 0);
112 /* Decrypt stdin to stdout, and exit */
116 char buf
[8*1024], *cp
;
119 while ((n
= fread(buf
, 1, sizeof buf
, stdin
)) > 0) {
120 if ((cp
= cipher(buf
, n
, 0)) == NULL
) {
121 fprintf(stderr
, "ermt: Error decoding input; see daemon.err syslog\n");
124 fwrite(cp
, 1, n
, stdout
);
127 perror("ermt: stdin: read");
130 if (fflush(stdout
)) {
131 perror("ermt: stdout: write");