Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-ece
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-ece
Commits
68bdc698
Commit
68bdc698
authored
Sep 05, 2019
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add an implementation of encrypt_record().
Test passes for the example in RFC8188 ch 3.1.
parent
7b322013
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
166 additions
and
11 deletions
+166
-11
rfc8188.c
src/rfc8188.c
+81
-0
rfc8188.h
src/rfc8188.h
+15
-4
rfc8188_test.c
src/rfc8188_test.c
+70
-7
No files found.
src/rfc8188.c
View file @
68bdc698
...
...
@@ -31,6 +31,8 @@
#include <openssl/hmac.h>
#include <openssl/err.h>
#include <string.h>
#include "rfc8188.h"
#ifndef VDEF_H_INCLUDED
...
...
@@ -60,6 +62,26 @@ mk_error(char *buf)
ERR_error_string
(
ERR_get_error
(),
NULL
));
}
/* copied from vend.h */
static
inline
void
be32enc
(
void
*
pp
,
uint32_t
u
)
{
uint8_t
*
p
=
(
uint8_t
*
)
pp
;
p
[
0
]
=
(
u
>>
24
)
&
0xff
;
p
[
1
]
=
(
u
>>
16
)
&
0xff
;
p
[
2
]
=
(
u
>>
8
)
&
0xff
;
p
[
3
]
=
u
&
0xff
;
}
void
encode_header
(
uint8_t
*
hdr
,
uint32_t
rs
,
uint8_t
idlen
,
uint8_t
*
keyid
)
{
be32enc
(
hdr
+
RS_OFF
,
rs
);
hdr
[
IDLEN_OFF
]
=
idlen
;
memcpy
(
hdr
+
ID_OFF
,
keyid
,
idlen
);
}
/* ch 2.2 pseudorandom key */
int
derive_prk
(
uint8_t
*
salt
,
uint8_t
*
key
,
unsigned
char
*
prk
,
char
*
errmsg
)
...
...
@@ -230,3 +252,62 @@ decrypt_record(EVP_CIPHER_CTX *ctx, unsigned char *ciphertext,
assert
(
end
>=
plaintext
);
return
(
end
-
plaintext
);
}
ssize_t
encrypt_record
(
EVP_CIPHER_CTX
*
ctx
,
unsigned
char
*
plaintext
,
int
plaintext_len
,
uint32_t
rs
,
uint8_t
cek
[
AES128_KEYLEN
],
unsigned
char
nonce
[
NONCE_LEN
],
int
last
,
unsigned
char
*
ciphertext
,
uint8_t
*
tag
,
char
errmsg
[
ERRMSG_LEN
])
{
int
delim_idx
,
len
,
ciphertext_len
;
AN
(
ctx
);
AN
(
plaintext
);
AN
(
cek
);
AN
(
nonce
);
AN
(
ciphertext
);
AN
(
errmsg
);
assert
(
plaintext_len
>=
0
);
assert
(
rs
>=
18
);
assert
((
unsigned
)
plaintext_len
<=
rs
-
(
TAG_LEN
+
1
));
delim_idx
=
rs
-
(
TAG_LEN
+
1
);
if
(
!
last
)
plaintext
[
delim_idx
]
=
'\1'
;
else
plaintext
[
delim_idx
]
=
'\2'
;
for
(
int
i
=
delim_idx
-
1
;
i
>
plaintext_len
;
i
--
)
plaintext
[
i
]
=
'\0'
;
if
(
EVP_CipherInit_ex
(
ctx
,
EVP_aes_128_gcm
(),
NULL
,
cek
,
nonce
,
-
1
)
!=
1
)
{
mk_error
(
errmsg
);
return
(
-
1
);
}
if
(
EVP_CipherUpdate
(
ctx
,
NULL
,
&
len
,
aad
,
aad_len
)
!=
1
)
{
mk_error
(
errmsg
);
return
(
-
1
);
}
if
(
EVP_CipherUpdate
(
ctx
,
ciphertext
,
&
len
,
plaintext
,
rs
-
TAG_LEN
)
!=
1
)
{
mk_error
(
errmsg
);
return
(
-
1
);
}
assert
(
rs
-
TAG_LEN
==
(
unsigned
)
len
);
ciphertext_len
=
len
;
if
((
EVP_CipherFinal_ex
(
ctx
,
ciphertext
+
ciphertext_len
,
&
len
))
!=
1
)
{
mk_error
(
errmsg
);
return
(
-
1
);
}
ciphertext_len
+=
len
;
if
(
!
EVP_CIPHER_CTX_ctrl
(
ctx
,
EVP_CTRL_GCM_GET_TAG
,
TAG_LEN
,
tag
))
{
mk_error
(
errmsg
);
return
(
-
1
);
}
return
(
ciphertext_len
);
}
src/rfc8188.h
View file @
68bdc698
...
...
@@ -76,6 +76,15 @@ decode_header(uint8_t *hdr, uint32_t *rs, uint8_t *idlen)
*
idlen
=
hdr
[
IDLEN_OFF
];
}
/*
* Output is hdr, inputs are rs, idlen and keyid. Salt is added
* separately.
*/
void
encode_header
(
uint8_t
*
hdr
,
uint32_t
rs
,
uint8_t
idlen
,
uint8_t
*
keyid
);
/* XXX implement me */
int
add_salt
(
unsigned
char
*
hdr
);
/*
* ch. 2.2 pseudorandom key
* Inputs are salt and key, output is prk. prk is re-used for both
...
...
@@ -137,7 +146,7 @@ cipher_ctx_fini(EVP_CIPHER_CTX *ctx)
* nonce results from XOR-ing the prenonce with the record sequence
* number.
*
* At least rs -
16
bytes must be allocated for the buffer at plaintext.
* At least rs -
TAG_LEN
bytes must be allocated for the buffer at plaintext.
*
* On return, *last is non-zero if this was the last record of the
* message, 0 otherwise.
...
...
@@ -153,9 +162,11 @@ ssize_t decrypt_record(EVP_CIPHER_CTX *ctx, unsigned char *ciphertext,
* Encrypt a record. Inputs are:
* plaintext, plaintext_len, rs, cek, nonce, last
* Outputs is:
* ciphertext
* ciphertext, tag
*
* The buffer at plaintext MUST have at least rs bytes allocated.
*
* plaintext_len MAY NOT be > rs -
17
.
* plaintext_len MAY NOT be > rs -
(TAG_LEN + 1)
.
*
* If last is non-zero, then this is the last record in the message.
*
...
...
@@ -168,4 +179,4 @@ ssize_t decrypt_record(EVP_CIPHER_CTX *ctx, unsigned char *ciphertext,
ssize_t
encrypt_record
(
EVP_CIPHER_CTX
*
ctx
,
unsigned
char
*
plaintext
,
int
plaintext_len
,
uint32_t
rs
,
uint8_t
cek
[
AES128_KEYLEN
],
unsigned
char
nonce
[
NONCE_LEN
],
int
last
,
unsigned
char
*
ciphertext
,
char
errmsg
[
ERRMSG_LEN
]);
uint8_t
tag
[
TAG_LEN
],
char
errmsg
[
ERRMSG_LEN
]);
src/rfc8188_test.c
View file @
68bdc698
...
...
@@ -84,11 +84,12 @@ int
main
(
int
argc
,
char
*
argv
[])
{
EVP_CIPHER_CTX
*
ctx
;
unsigned
char
prk_b64
[
45
],
cek_b64
[
25
],
nonce_b64
[
17
];
unsigned
char
prk_b64
[
45
],
cek_b64
[
25
],
nonce_b64
[
17
],
body1_test_b64
[
73
];
unsigned
char
key1
[
AES128_KEYLEN
+
2
],
key2
[
AES128_KEYLEN
+
2
],
salt
[
SALT_LEN
+
2
],
prk
[
SHA256_LEN
],
cek
[
SHA256_LEN
],
nonce
[
SHA256_LEN
],
seq
[
NONCE_LEN
]
;
unsigned
char
body1
[
54
],
body2
[
75
],
plaintext
[
64
],
*
ciphertext
;
nonce
[
SHA256_LEN
],
seq
[
NONCE_LEN
]
,
tag
[
TAG_LEN
],
body1
[
54
],
body2
[
75
],
plaintext
[
64
],
*
ciphertext
;
char
errmsg
[
ERRMSG_LEN
];
uint32_t
rs
;
uint8_t
idlen
;
...
...
@@ -105,7 +106,7 @@ main(int argc, char *argv[])
assert
(
len
==
SALT_LEN
+
2
);
if
(
derive_prk
(
salt
,
key1
,
prk
,
errmsg
)
!=
0
)
{
fprintf
(
stderr
,
"ex1 PRK: %s
\n
"
,
errmsg
);
fprintf
(
stderr
,
"ex1
decrypt
PRK: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
...
...
@@ -114,7 +115,7 @@ main(int argc, char *argv[])
AZ
(
memcmp
(
prk_b64
,
prk1_b64
,
len
));
if
(
derive_cek
(
prk
,
cek
,
errmsg
)
!=
0
)
{
fprintf
(
stderr
,
"ex1 CEK: %s
\n
"
,
errmsg
);
fprintf
(
stderr
,
"ex1
decrypt
CEK: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
...
...
@@ -124,7 +125,7 @@ main(int argc, char *argv[])
memset
(
seq
,
0
,
NONCE_LEN
);
if
(
derive_prenonce
(
prk
,
nonce
,
errmsg
)
!=
0
)
{
fprintf
(
stderr
,
"ex1 NONCE: %s
\n
"
,
errmsg
);
fprintf
(
stderr
,
"ex1
decrypt
NONCE: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
...
...
@@ -142,7 +143,7 @@ main(int argc, char *argv[])
assert
(
idlen
==
exp_idlen1
);
if
((
ctx
=
cipher_ctx_init
(
0
,
errmsg
))
==
NULL
)
{
fprintf
(
stderr
,
"ex1: cipher_ctx_init: %s
\n
"
,
errmsg
);
fprintf
(
stderr
,
"ex1
decrypt
: cipher_ctx_init: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
...
...
@@ -217,6 +218,68 @@ main(int argc, char *argv[])
plaintext_len
+=
len
;
AZ
(
memcmp
(
plaintext
,
exp_plaintext
,
len
));
cipher_ctx_fini
(
ctx
);
/* example 1, ch 3.1, encryption */
memset
(
plaintext
,
0xff
,
64
);
memcpy
(
plaintext
,
exp_plaintext
,
exp_plaintext_len
);
/* Ordinarily call add_salt() to get random salt. */
memcpy
(
body1
,
salt
,
SALT_LEN
);
encode_header
(
body1
,
exp_rs1
,
exp_idlen1
,
(
unsigned
char
*
)
""
);
if
(
derive_prk
(
body1
,
key1
,
prk
,
errmsg
)
!=
0
)
{
fprintf
(
stderr
,
"ex1 encrypt PRK: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
len
=
EVP_EncodeBlock
(
prk_b64
,
prk
,
SHA256_LEN
);
assert
(
len
==
44
);
AZ
(
memcmp
(
prk_b64
,
prk1_b64
,
len
));
if
(
derive_cek
(
prk
,
cek
,
errmsg
)
!=
0
)
{
fprintf
(
stderr
,
"ex1 encrypt CEK: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
len
=
EVP_EncodeBlock
(
cek_b64
,
cek
,
AES128_KEYLEN
);
assert
(
len
==
24
);
AZ
(
memcmp
(
cek_b64
,
cek1_b64
,
len
));
seq
[
NONCE_LEN
-
1
]
=
0
;
// simulates reset to 0
if
(
derive_prenonce
(
prk
,
nonce
,
errmsg
)
!=
0
)
{
fprintf
(
stderr
,
"ex1 encrypt NONCE: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
len
=
EVP_EncodeBlock
(
nonce_b64
,
nonce
,
NONCE_LEN
);
assert
(
len
==
16
);
AZ
(
memcmp
(
nonce_b64
,
nonce1_b64
,
len
));
if
((
ctx
=
cipher_ctx_init
(
1
,
errmsg
))
==
NULL
)
{
fprintf
(
stderr
,
"ex1 encrypt: cipher_ctx_init: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
/* Using a shorter record size */
rs
=
32
;
assert
(
rs
+
HDR_PREFIX_LEN
+
exp_idlen1
==
bodylen1
);
last
=
1
;
ciphertext
=
body1
+
HDR_PREFIX_LEN
+
exp_idlen1
;
len
=
encrypt_record
(
ctx
,
plaintext
,
exp_plaintext_len
,
rs
,
cek
,
nonce
,
last
,
ciphertext
,
tag
,
errmsg
);
if
(
len
<
0
)
{
fprintf
(
stderr
,
"ex1 encrypt_record: %s
\n
"
,
errmsg
);
exit
(
-
1
);
}
assert
((
unsigned
)
len
==
rs
-
TAG_LEN
);
memcpy
(
ciphertext
+
(
rs
-
TAG_LEN
),
tag
,
TAG_LEN
);
len
=
EVP_EncodeBlock
(
body1_test_b64
,
body1
,
bodylen1
);
assert
(
len
==
72
);
AZ
(
memcmp
(
body1_test_b64
,
body1_b64
,
len
));
cipher_ctx_fini
(
ctx
);
exit
(
0
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment