Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
btwise
openssl
提交
c857a80c
O
openssl
项目概览
btwise
/
openssl
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
openssl
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c857a80c
编写于
12月 06, 2014
作者:
M
Matt Caswell
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for OCB mode as per RFC7253
Reviewed-by:
N
Tim Hudson
<
tjh@openssl.org
>
上级
376e2ca3
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
656 addition
and
2 deletion
+656
-2
crypto/modes/Makefile
crypto/modes/Makefile
+7
-2
crypto/modes/modes.h
crypto/modes/modes.h
+23
-0
crypto/modes/modes_lcl.h
crypto/modes/modes_lcl.h
+39
-0
crypto/modes/ocb128.c
crypto/modes/ocb128.c
+587
-0
未找到文件。
crypto/modes/Makefile
浏览文件 @
c857a80c
...
...
@@ -22,9 +22,9 @@ APPS=
LIB
=
$(TOP)
/libcrypto.a
LIBSRC
=
cbc128.c ctr128.c cts128.c cfb128.c ofb128.c gcm128.c
\
ccm128.c xts128.c wrap128.c
ccm128.c xts128.c wrap128.c
ocb128.c
LIBOBJ
=
cbc128.o ctr128.o cts128.o cfb128.o ofb128.o gcm128.o
\
ccm128.o xts128.o wrap128.o
$(MODES_ASM_OBJ)
ccm128.o xts128.o wrap128.o
ocb128.o
$(MODES_ASM_OBJ)
SRC
=
$(LIBSRC)
...
...
@@ -138,6 +138,11 @@ gcm128.o: ../../include/openssl/modes.h ../../include/openssl/opensslconf.h
gcm128.o
:
../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gcm128.o
:
../../include/openssl/safestack.h ../../include/openssl/stack.h
gcm128.o
:
../../include/openssl/symhacks.h gcm128.c modes_lcl.h
ocb128.o
:
../../include/openssl/crypto.h ../../include/openssl/e_os2.h
ocb128.o
:
../../include/openssl/modes.h ../../include/openssl/opensslconf.h
ocb128.o
:
../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
ocb128.o
:
../../include/openssl/safestack.h ../../include/openssl/stack.h
ocb128.o
:
../../include/openssl/symhacks.h modes_lcl.h ocb128.c
ofb128.o
:
../../include/openssl/crypto.h ../../include/openssl/e_os2.h
ofb128.o
:
../../include/openssl/modes.h ../../include/openssl/opensslconf.h
ofb128.o
:
../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
...
...
crypto/modes/modes.h
浏览文件 @
c857a80c
...
...
@@ -137,6 +137,7 @@ typedef struct xts128_context XTS128_CONTEXT;
int
CRYPTO_xts128_encrypt
(
const
XTS128_CONTEXT
*
ctx
,
const
unsigned
char
iv
[
16
],
const
unsigned
char
*
inp
,
unsigned
char
*
out
,
size_t
len
,
int
enc
);
size_t
CRYPTO_128_wrap
(
void
*
key
,
const
unsigned
char
*
iv
,
unsigned
char
*
out
,
const
unsigned
char
*
in
,
size_t
inlen
,
block128_f
block
);
...
...
@@ -150,6 +151,28 @@ size_t CRYPTO_128_wrap_pad(void *key, const unsigned char *icv,
size_t
CRYPTO_128_unwrap_pad
(
void
*
key
,
const
unsigned
char
*
icv
,
unsigned
char
*
out
,
const
unsigned
char
*
in
,
size_t
inlen
,
block128_f
block
);
typedef
struct
ocb128_context
OCB128_CONTEXT
;
OCB128_CONTEXT
*
CRYPTO_ocb128_new
(
void
*
keyenc
,
void
*
keydec
,
block128_f
encrypt
,
block128_f
decrypt
);
int
CRYPTO_ocb128_init
(
OCB128_CONTEXT
*
ctx
,
void
*
keyenc
,
void
*
keydec
,
block128_f
encrypt
,
block128_f
decrypt
);
int
CRYPTO_ocb128_copy_ctx
(
OCB128_CONTEXT
*
dest
,
OCB128_CONTEXT
*
src
,
void
*
keyenc
,
void
*
keydec
);
int
CRYPTO_ocb128_setiv
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
iv
,
size_t
len
,
size_t
taglen
);
int
CRYPTO_ocb128_aad
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
aad
,
size_t
len
);
int
CRYPTO_ocb128_encrypt
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
in
,
unsigned
char
*
out
,
size_t
len
);
int
CRYPTO_ocb128_decrypt
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
in
,
unsigned
char
*
out
,
size_t
len
);
int
CRYPTO_ocb128_finish
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
tag
,
size_t
len
);
int
CRYPTO_ocb128_tag
(
OCB128_CONTEXT
*
ctx
,
unsigned
char
*
tag
,
size_t
len
);
void
CRYPTO_ocb128_cleanup
(
OCB128_CONTEXT
*
ctx
);
#ifdef __cplusplus
}
#endif
crypto/modes/modes_lcl.h
浏览文件 @
c857a80c
...
...
@@ -136,3 +136,42 @@ struct ccm128_context {
void
*
key
;
};
#ifdef STRICT_ALIGNMENT
typedef
struct
{
unsigned
char
a
[
16
];
}
OCB_BLOCK
;
# define ocb_block16_xor(in1,in2,out) \
ocb_block_xor((in1)->a,(in2)->a,16,(out)->a)
#else
typedef
struct
{
u64
a
;
u64
b
;
}
OCB_BLOCK
;
# define ocb_block16_xor(in1,in2,out) \
(out)->a=(in1)->a^(in2)->a; (out)->b=(in1)->b^(in2)->b;
#endif
struct
ocb128_context
{
/* Need both encrypt and decrypt key schedules for decryption */
block128_f
encrypt
;
block128_f
decrypt
;
void
*
keyenc
;
void
*
keydec
;
/* Key dependent variables. Can be reused if key remains the same */
size_t
l_index
;
size_t
max_l_index
;
OCB_BLOCK
l_star
;
OCB_BLOCK
l_dollar
;
OCB_BLOCK
*
l
;
/* Must be reset for each session */
u64
blocks_hashed
;
u64
blocks_processed
;
OCB_BLOCK
tag
;
OCB_BLOCK
offset_aad
;
OCB_BLOCK
sum
;
OCB_BLOCK
offset
;
OCB_BLOCK
checksum
;
};
crypto/modes/ocb128.c
0 → 100644
浏览文件 @
c857a80c
/* ====================================================================
* Copyright (c) 2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/crypto.h>
#include "modes_lcl.h"
union
ublock
{
unsigned
char
*
chrblk
;
OCB_BLOCK
*
ocbblk
;
};
/*
* Calculate the number of binary trailing zero's in any given number
*/
static
u32
ocb_ntz
(
u64
n
)
{
u32
cnt
=
0
;
/*
* We do a right-to-left simple sequential search. This is surprisingly
* efficient as the distribution of trailing zeros is not uniform,
* e.g. the number of possible inputs with no trailing zeros is equal to
* the number with 1 or more; the number with exactly 1 is equal to the
* number with 2 or more, etc. Checking the last two bits covers 75% of
* all numbers. Checking the last three covers 87.5%
*/
while
(
!
(
n
&
1
))
{
n
>>=
1
;
cnt
++
;
}
return
cnt
;
}
/*
* Shift a block of 16 bytes left by shift bits
*/
static
void
ocb_block_lshift
(
OCB_BLOCK
*
in
,
size_t
shift
,
OCB_BLOCK
*
out
)
{
unsigned
char
shift_mask
;
int
i
;
unsigned
char
mask
[
15
];
union
ublock
locin
;
union
ublock
locout
;
locin
.
ocbblk
=
in
;
locout
.
ocbblk
=
out
;
shift_mask
=
0xff
;
shift_mask
<<=
(
8
-
shift
);
for
(
i
=
15
;
i
>=
0
;
i
--
)
{
if
(
i
>
0
)
{
mask
[
i
-
1
]
=
locin
.
chrblk
[
i
]
&
shift_mask
;
mask
[
i
-
1
]
>>=
8
-
shift
;
}
locout
.
chrblk
[
i
]
=
locin
.
chrblk
[
i
]
<<
shift
;
if
(
i
!=
15
)
{
locout
.
chrblk
[
i
]
^=
mask
[
i
];
}
}
}
/*
* Perform a "double" operation as per OCB spec
*/
static
void
ocb_double
(
OCB_BLOCK
*
in
,
OCB_BLOCK
*
out
)
{
unsigned
char
mask
;
union
ublock
locin
;
union
ublock
locout
;
locin
.
ocbblk
=
in
;
locout
.
ocbblk
=
out
;
/*
* Calculate the mask based on the most significant bit. There are more
* efficient ways to do this - but this way is constant time
*/
mask
=
locin
.
chrblk
[
0
]
&
0x80
;
mask
>>=
7
;
mask
*=
135
;
ocb_block_lshift
(
in
,
1
,
out
);
locout
.
chrblk
[
15
]
^=
mask
;
}
/*
* Perform an xor on in1 and in2 - each of len bytes. Store result in out
*/
static
void
ocb_block_xor
(
const
unsigned
char
*
in1
,
const
unsigned
char
*
in2
,
size_t
len
,
unsigned
char
*
out
)
{
size_t
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
out
[
i
]
=
in1
[
i
]
^
in2
[
i
];
}
}
/*
* Lookup L_index in our lookup table. If we haven't already got it we need to
* calculate it
*/
static
OCB_BLOCK
*
ocb_lookup_l
(
OCB128_CONTEXT
*
ctx
,
size_t
index
)
{
if
(
index
<=
ctx
->
l_index
)
{
return
ctx
->
l
+
index
;
}
/* We don't have it - so calculate it */
ctx
->
l_index
++
;
if
(
ctx
->
l_index
==
ctx
->
max_l_index
)
{
ctx
->
max_l_index
*=
2
;
ctx
->
l
=
OPENSSL_realloc
(
ctx
->
l
,
ctx
->
max_l_index
*
sizeof
(
OCB_BLOCK
));
if
(
!
ctx
->
l
)
return
NULL
;
}
ocb_double
(
ctx
->
l
+
(
index
-
1
),
ctx
->
l
+
index
);
return
ctx
->
l
+
index
;
}
/*
* Encrypt a block from |in| and store the result in |out|
*/
static
void
ocb_encrypt
(
OCB128_CONTEXT
*
ctx
,
OCB_BLOCK
*
in
,
OCB_BLOCK
*
out
,
void
*
keyenc
)
{
union
ublock
locin
;
union
ublock
locout
;
locin
.
ocbblk
=
in
;
locout
.
ocbblk
=
out
;
ctx
->
encrypt
(
locin
.
chrblk
,
locout
.
chrblk
,
keyenc
);
}
/*
* Decrypt a block from |in| and store the result in |out|
*/
static
void
ocb_decrypt
(
OCB128_CONTEXT
*
ctx
,
OCB_BLOCK
*
in
,
OCB_BLOCK
*
out
,
void
*
keydec
)
{
union
ublock
locin
;
union
ublock
locout
;
locin
.
ocbblk
=
in
;
locout
.
ocbblk
=
out
;
ctx
->
decrypt
(
locin
.
chrblk
,
locout
.
chrblk
,
keydec
);
}
/*
* Create a new OCB128_CONTEXT
*/
OCB128_CONTEXT
*
CRYPTO_ocb128_new
(
void
*
keyenc
,
void
*
keydec
,
block128_f
encrypt
,
block128_f
decrypt
)
{
OCB128_CONTEXT
*
octx
;
int
ret
;
if
((
octx
=
(
OCB128_CONTEXT
*
)
OPENSSL_malloc
(
sizeof
(
OCB128_CONTEXT
))))
{
ret
=
CRYPTO_ocb128_init
(
octx
,
keyenc
,
keydec
,
encrypt
,
decrypt
);
if
(
ret
)
return
octx
;
OPENSSL_free
(
octx
);
}
return
NULL
;
}
/*
* Initialise an existing OCB128_CONTEXT
*/
int
CRYPTO_ocb128_init
(
OCB128_CONTEXT
*
ctx
,
void
*
keyenc
,
void
*
keydec
,
block128_f
encrypt
,
block128_f
decrypt
)
{
/* Clear everything to NULLs */
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
ctx
->
l_index
=
0
;
ctx
->
max_l_index
=
1
;
ctx
->
l
=
OPENSSL_malloc
(
ctx
->
max_l_index
*
16
);
if
(
!
ctx
->
l
)
return
0
;
/*
* We set both the encryption and decryption key schedules - decryption
* needs both. Don't really need decryption schedule if only doing
* encryption - but it simplifies things to take it anyway
*/
ctx
->
encrypt
=
encrypt
;
ctx
->
decrypt
=
decrypt
;
ctx
->
keyenc
=
keyenc
;
ctx
->
keydec
=
keydec
;
/* L_* = ENCIPHER(K, zeros(128)) */
ocb_encrypt
(
ctx
,
&
ctx
->
l_star
,
&
ctx
->
l_star
,
ctx
->
keyenc
);
/* L_$ = double(L_*) */
ocb_double
(
&
ctx
->
l_star
,
&
ctx
->
l_dollar
);
/* L_0 = double(L_$) */
ocb_double
(
&
ctx
->
l_dollar
,
ctx
->
l
);
return
1
;
}
/*
* Copy an OCB128_CONTEXT object
*/
int
CRYPTO_ocb128_copy_ctx
(
OCB128_CONTEXT
*
dest
,
OCB128_CONTEXT
*
src
,
void
*
keyenc
,
void
*
keydec
)
{
memcpy
(
dest
,
src
,
sizeof
(
OCB128_CONTEXT
));
if
(
keyenc
)
dest
->
keyenc
=
keyenc
;
if
(
keydec
)
dest
->
keydec
=
keydec
;
if
(
src
->
l
)
{
dest
->
l
=
OPENSSL_malloc
(
src
->
max_l_index
*
16
);
if
(
!
dest
->
l
)
return
0
;
memcpy
(
dest
->
l
,
src
->
l
,
(
src
->
l_index
+
1
)
*
16
);
}
return
1
;
}
/*
* Set the IV to be used for this operation. Must be 1 - 15 bytes.
*/
int
CRYPTO_ocb128_setiv
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
iv
,
size_t
len
,
size_t
taglen
)
{
unsigned
char
ktop
[
16
],
tmp
[
16
],
mask
;
unsigned
char
stretch
[
24
],
nonce
[
16
];
size_t
bottom
,
shift
;
union
ublock
offset
;
offset
.
ocbblk
=
&
ctx
->
offset
;
/*
* Spec says IV is 120 bits or fewer - it allows non byte aligned lengths.
* We don't support this at this stage
*/
if
((
len
>
15
)
||
(
len
<
1
)
||
(
taglen
>
16
)
||
(
taglen
<
1
))
{
return
-
1
;
}
/* Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N */
nonce
[
0
]
=
((
taglen
*
8
)
%
128
)
<<
1
;
memset
(
nonce
+
1
,
0
,
15
);
memcpy
(
nonce
+
16
-
len
,
iv
,
len
);
nonce
[
15
-
len
]
|=
1
;
/* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */
memcpy
(
tmp
,
nonce
,
16
);
tmp
[
15
]
&=
0xc0
;
ctx
->
encrypt
(
tmp
,
ktop
,
ctx
->
keyenc
);
/* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
memcpy
(
stretch
,
ktop
,
16
);
ocb_block_xor
(
ktop
,
ktop
+
1
,
8
,
stretch
+
16
);
/* bottom = str2num(Nonce[123..128]) */
bottom
=
nonce
[
15
]
&
0x3f
;
/* Offset_0 = Stretch[1+bottom..128+bottom] */
shift
=
bottom
%
8
;
ocb_block_lshift
((
OCB_BLOCK
*
)(
stretch
+
(
bottom
/
8
)),
shift
,
&
ctx
->
offset
);
mask
=
0xff
;
mask
<<=
8
-
shift
;
offset
.
chrblk
[
15
]
|=
(
*
(
stretch
+
(
bottom
/
8
)
+
16
)
&
mask
)
>>
(
8
-
shift
);
return
1
;
}
/*
* Provide any AAD. This can be called multiple times. Only the final time can
* have a partial block
*/
int
CRYPTO_ocb128_aad
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
aad
,
size_t
len
)
{
u64
all_num_blocks
,
num_blocks
;
u64
i
;
OCB_BLOCK
tmp1
;
OCB_BLOCK
tmp2
;
int
last_len
;
/* Calculate the number of blocks of AAD provided now, and so far */
num_blocks
=
len
/
16
;
all_num_blocks
=
num_blocks
+
ctx
->
blocks_hashed
;
/* Loop through all full blocks of AAD */
for
(
i
=
ctx
->
blocks_hashed
+
1
;
i
<=
all_num_blocks
;
i
++
)
{
OCB_BLOCK
*
lookup
;
OCB_BLOCK
*
aad_block
;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
lookup
=
ocb_lookup_l
(
ctx
,
ocb_ntz
(
i
));
if
(
!
lookup
)
return
0
;
ocb_block16_xor
(
&
ctx
->
offset_aad
,
lookup
,
&
ctx
->
offset_aad
);
/* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
aad_block
=
(
OCB_BLOCK
*
)
(
aad
+
((
i
-
ctx
->
blocks_hashed
-
1
)
*
16
));
ocb_block16_xor
(
&
ctx
->
offset_aad
,
aad_block
,
&
tmp1
);
ocb_encrypt
(
ctx
,
&
tmp1
,
&
tmp2
,
ctx
->
keyenc
);
ocb_block16_xor
(
&
ctx
->
sum
,
&
tmp2
,
&
ctx
->
sum
);
}
/*
* Check if we have any partial blocks left over. This is only valid in the
* last call to this function
*/
last_len
=
len
%
16
;
if
(
last_len
>
0
)
{
/* Offset_* = Offset_m xor L_* */
ocb_block16_xor
(
&
ctx
->
offset_aad
,
&
ctx
->
l_star
,
&
ctx
->
offset_aad
);
/* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */
memset
((
void
*
)
&
tmp1
,
0
,
16
);
memcpy
((
void
*
)
&
tmp1
,
aad
+
(
num_blocks
*
16
),
last_len
);
((
unsigned
char
*
)
&
tmp1
)[
last_len
]
=
0x80
;
ocb_block16_xor
(
&
ctx
->
offset_aad
,
&
tmp1
,
&
tmp2
);
/* Sum = Sum_m xor ENCIPHER(K, CipherInput) */
ocb_encrypt
(
ctx
,
&
tmp2
,
&
tmp1
,
ctx
->
keyenc
);
ocb_block16_xor
(
&
ctx
->
sum
,
&
tmp1
,
&
ctx
->
sum
);
}
ctx
->
blocks_hashed
=
all_num_blocks
;
return
1
;
}
/*
* Provide any data to be encrypted. This can be called multiple times. Only
* the final time can have a partial block
*/
int
CRYPTO_ocb128_encrypt
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
in
,
unsigned
char
*
out
,
size_t
len
)
{
u64
i
;
u64
all_num_blocks
,
num_blocks
;
OCB_BLOCK
tmp1
;
OCB_BLOCK
tmp2
;
OCB_BLOCK
pad
;
int
last_len
;
/*
* Calculate the number of blocks of data to be encrypted provided now, and
* so far
*/
num_blocks
=
len
/
16
;
all_num_blocks
=
num_blocks
+
ctx
->
blocks_processed
;
/* Loop through all full blocks to be encrypted */
for
(
i
=
ctx
->
blocks_processed
+
1
;
i
<=
all_num_blocks
;
i
++
)
{
OCB_BLOCK
*
lookup
;
OCB_BLOCK
*
inblock
;
OCB_BLOCK
*
outblock
;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
lookup
=
ocb_lookup_l
(
ctx
,
ocb_ntz
(
i
));
if
(
!
lookup
)
return
0
;
ocb_block16_xor
(
&
ctx
->
offset
,
lookup
,
&
ctx
->
offset
);
/* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
inblock
=
(
OCB_BLOCK
*
)
(
in
+
((
i
-
ctx
->
blocks_processed
-
1
)
*
16
));
ocb_block16_xor
(
&
ctx
->
offset
,
inblock
,
&
tmp1
);
ocb_encrypt
(
ctx
,
&
tmp1
,
&
tmp2
,
ctx
->
keyenc
);
outblock
=
(
OCB_BLOCK
*
)
(
out
+
((
i
-
ctx
->
blocks_processed
-
1
)
*
16
));
ocb_block16_xor
(
&
ctx
->
offset
,
&
tmp2
,
outblock
);
/* Checksum_i = Checksum_{i-1} xor P_i */
ocb_block16_xor
(
&
ctx
->
checksum
,
inblock
,
&
ctx
->
checksum
);
}
/*
* Check if we have any partial blocks left over. This is only valid in the
* last call to this function
*/
last_len
=
len
%
16
;
if
(
last_len
>
0
)
{
/* Offset_* = Offset_m xor L_* */
ocb_block16_xor
(
&
ctx
->
offset
,
&
ctx
->
l_star
,
&
ctx
->
offset
);
/* Pad = ENCIPHER(K, Offset_*) */
ocb_encrypt
(
ctx
,
&
ctx
->
offset
,
&
pad
,
ctx
->
keyenc
);
/* C_* = P_* xor Pad[1..bitlen(P_*)] */
ocb_block_xor
(
in
+
(
len
/
16
)
*
16
,
(
unsigned
char
*
)
&
pad
,
last_len
,
out
+
(
num_blocks
*
16
));
/* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
memset
((
void
*
)
&
tmp1
,
0
,
16
);
memcpy
((
void
*
)
&
tmp1
,
in
+
(
len
/
16
)
*
16
,
last_len
);
((
unsigned
char
*
)(
&
tmp1
))[
last_len
]
=
0x80
;
ocb_block16_xor
(
&
ctx
->
checksum
,
&
tmp1
,
&
ctx
->
checksum
);
}
ctx
->
blocks_processed
=
all_num_blocks
;
return
1
;
}
/*
* Provide any data to be decrypted. This can be called multiple times. Only
* the final time can have a partial block
*/
int
CRYPTO_ocb128_decrypt
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
in
,
unsigned
char
*
out
,
size_t
len
)
{
u64
i
;
u64
all_num_blocks
,
num_blocks
;
OCB_BLOCK
tmp1
;
OCB_BLOCK
tmp2
;
OCB_BLOCK
pad
;
int
last_len
;
/*
* Calculate the number of blocks of data to be decrypted provided now, and
* so far
*/
num_blocks
=
len
/
16
;
all_num_blocks
=
num_blocks
+
ctx
->
blocks_processed
;
/* Loop through all full blocks to be decrypted */
for
(
i
=
ctx
->
blocks_processed
+
1
;
i
<=
all_num_blocks
;
i
++
)
{
OCB_BLOCK
*
inblock
;
OCB_BLOCK
*
outblock
;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
OCB_BLOCK
*
lookup
=
ocb_lookup_l
(
ctx
,
ocb_ntz
(
i
));
if
(
!
lookup
)
return
0
;
ocb_block16_xor
(
&
ctx
->
offset
,
lookup
,
&
ctx
->
offset
);
/* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
inblock
=
(
OCB_BLOCK
*
)
(
in
+
((
i
-
ctx
->
blocks_processed
-
1
)
*
16
));
ocb_block16_xor
(
&
ctx
->
offset
,
inblock
,
&
tmp1
);
ocb_decrypt
(
ctx
,
&
tmp1
,
&
tmp2
,
ctx
->
keydec
);
outblock
=
(
OCB_BLOCK
*
)
(
out
+
((
i
-
ctx
->
blocks_processed
-
1
)
*
16
));
ocb_block16_xor
(
&
ctx
->
offset
,
&
tmp2
,
outblock
);
/* Checksum_i = Checksum_{i-1} xor P_i */
ocb_block16_xor
(
&
ctx
->
checksum
,
outblock
,
&
ctx
->
checksum
);
}
/*
* Check if we have any partial blocks left over. This is only valid in the
* last call to this function
*/
last_len
=
len
%
16
;
if
(
last_len
>
0
)
{
/* Offset_* = Offset_m xor L_* */
ocb_block16_xor
(
&
ctx
->
offset
,
&
ctx
->
l_star
,
&
ctx
->
offset
);
/* Pad = ENCIPHER(K, Offset_*) */
ocb_encrypt
(
ctx
,
&
ctx
->
offset
,
&
pad
,
ctx
->
keyenc
);
/* P_* = C_* xor Pad[1..bitlen(C_*)] */
ocb_block_xor
(
in
+
(
len
/
16
)
*
16
,
(
unsigned
char
*
)
&
pad
,
last_len
,
out
+
(
num_blocks
*
16
));
/* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
memset
((
void
*
)
&
tmp1
,
0
,
16
);
memcpy
((
void
*
)
&
tmp1
,
out
+
(
len
/
16
)
*
16
,
last_len
);
((
unsigned
char
*
)(
&
tmp1
))[
last_len
]
=
0x80
;
ocb_block16_xor
(
&
ctx
->
checksum
,
&
tmp1
,
&
ctx
->
checksum
);
}
ctx
->
blocks_processed
=
all_num_blocks
;
return
1
;
}
/*
* Calculate the tag and verify it against the supplied tag
*/
int
CRYPTO_ocb128_finish
(
OCB128_CONTEXT
*
ctx
,
const
unsigned
char
*
tag
,
size_t
len
)
{
OCB_BLOCK
tmp1
,
tmp2
;
/*Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */
ocb_block16_xor
(
&
ctx
->
checksum
,
&
ctx
->
offset
,
&
tmp1
);
ocb_block16_xor
(
&
tmp1
,
&
ctx
->
l_dollar
,
&
tmp2
);
ocb_encrypt
(
ctx
,
&
tmp2
,
&
tmp1
,
ctx
->
keyenc
);
ocb_block16_xor
(
&
tmp1
,
&
ctx
->
sum
,
&
ctx
->
tag
);
if
(
len
>
16
||
len
<
1
)
{
return
-
1
;
}
/* Compare the tag if we've been given one */
if
(
tag
)
return
CRYPTO_memcmp
(
&
ctx
->
tag
,
tag
,
len
);
else
return
-
1
;
}
/*
* Retrieve the calculated tag
*/
int
CRYPTO_ocb128_tag
(
OCB128_CONTEXT
*
ctx
,
unsigned
char
*
tag
,
size_t
len
)
{
if
(
len
>
16
||
len
<
1
)
{
return
-
1
;
}
/* Calculate the tag */
CRYPTO_ocb128_finish
(
ctx
,
NULL
,
0
);
/* Copy the tag into the supplied buffer */
memcpy
(
tag
,
&
ctx
->
tag
,
len
);
return
1
;
}
/*
* Release all resources
*/
void
CRYPTO_ocb128_cleanup
(
OCB128_CONTEXT
*
ctx
)
{
if
(
ctx
)
{
if
(
ctx
->
l
)
{
OPENSSL_cleanse
(
ctx
->
l
,
ctx
->
max_l_index
*
16
);
OPENSSL_free
(
ctx
->
l
);
}
OPENSSL_cleanse
(
ctx
,
sizeof
(
*
ctx
));
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录