Initial import.
This commit is contained in:
commit
3210f38e04
292 changed files with 58526 additions and 0 deletions
44
src/codec/ccopy.c
Normal file
44
src/codec/ccopy.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len)
|
||||
{
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
|
||||
d = dst;
|
||||
s = src;
|
||||
while (len -- > 0) {
|
||||
uint32_t x, y;
|
||||
|
||||
x = *s ++;
|
||||
y = *d;
|
||||
*d = MUX(ctl, x, y);
|
||||
d ++;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec16be.c
Normal file
38
src/codec/dec16be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec16be(uint16_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec16be(buf);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec16le.c
Normal file
38
src/codec/dec16le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec16le(uint16_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec16le(buf);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec32be.c
Normal file
38
src/codec/dec32be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec32be(uint32_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec32be(buf);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec32le.c
Normal file
38
src/codec/dec32le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec32le(uint32_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec32le(buf);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec64be.c
Normal file
38
src/codec/dec64be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec64be(uint64_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec64be(buf);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec64le.c
Normal file
38
src/codec/dec64le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec64le(uint64_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec64le(buf);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc16be.c
Normal file
38
src/codec/enc16be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc16be(void *dst, const uint16_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc16be(buf, *v ++);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc16le.c
Normal file
38
src/codec/enc16le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc16le(void *dst, const uint16_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc16le(buf, *v ++);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc32be.c
Normal file
38
src/codec/enc32be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc32be(void *dst, const uint32_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc32be(buf, *v ++);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc32le.c
Normal file
38
src/codec/enc32le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc32le(void *dst, const uint32_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc32le(buf, *v ++);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc64be.c
Normal file
38
src/codec/enc64be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc64be(void *dst, const uint64_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc64be(buf, *v ++);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc64le.c
Normal file
38
src/codec/enc64le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc64le(void *dst, const uint64_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc64le(buf, *v ++);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
508
src/codec/pemdec.c
Normal file
508
src/codec/pemdec.c
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
/* Automatically generated code; do not modify directly. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t *dp;
|
||||
uint32_t *rp;
|
||||
const unsigned char *ip;
|
||||
} t0_context;
|
||||
|
||||
static uint32_t
|
||||
t0_parse7E_unsigned(const unsigned char **p)
|
||||
{
|
||||
uint32_t x;
|
||||
|
||||
x = 0;
|
||||
for (;;) {
|
||||
unsigned y;
|
||||
|
||||
y = *(*p) ++;
|
||||
x = (x << 7) | (uint32_t)(y & 0x7F);
|
||||
if (y < 0x80) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t
|
||||
t0_parse7E_signed(const unsigned char **p)
|
||||
{
|
||||
int neg;
|
||||
uint32_t x;
|
||||
|
||||
neg = ((**p) >> 6) & 1;
|
||||
x = (uint32_t)-neg;
|
||||
for (;;) {
|
||||
unsigned y;
|
||||
|
||||
y = *(*p) ++;
|
||||
x = (x << 7) | (uint32_t)(y & 0x7F);
|
||||
if (y < 0x80) {
|
||||
if (neg) {
|
||||
return -(int32_t)~x - 1;
|
||||
} else {
|
||||
return (int32_t)x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
|
||||
#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
|
||||
#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
|
||||
#define T0_INT1(x) T0_FBYTE(x, 0)
|
||||
#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
|
||||
static const uint8_t t0_datablock[];
|
||||
|
||||
|
||||
void br_pem_decoder_init_main(void *t0ctx);
|
||||
|
||||
void br_pem_decoder_run(void *t0ctx);
|
||||
|
||||
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CTX ((br_pem_decoder_context *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
void
|
||||
br_pem_decoder_init(br_pem_decoder_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
ctx->cpu.dp = &ctx->dp_stack[0];
|
||||
ctx->cpu.rp = &ctx->rp_stack[0];
|
||||
br_pem_decoder_init_main(&ctx->cpu);
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
size_t
|
||||
br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (ctx->event) {
|
||||
return 0;
|
||||
}
|
||||
ctx->hbuf = data;
|
||||
ctx->hlen = len;
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
return len - ctx->hlen;
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
int
|
||||
br_pem_decoder_event(br_pem_decoder_context *ctx)
|
||||
{
|
||||
int event;
|
||||
|
||||
event = ctx->event;
|
||||
ctx->event = 0;
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const uint8_t t0_datablock[] = {
|
||||
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20,
|
||||
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00
|
||||
};
|
||||
|
||||
static const uint8_t t0_codeblock[] = {
|
||||
0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01,
|
||||
0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01,
|
||||
T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01,
|
||||
T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05,
|
||||
0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01,
|
||||
0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27,
|
||||
0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00,
|
||||
0x01, 0x01, 0x7F, 0x03, 0x00, 0x24, 0x01, 0x00, 0x17, 0x0D, 0x06, 0x03,
|
||||
0x13, 0x04, 0x3C, 0x01, 0x7F, 0x17, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00,
|
||||
0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x22, 0x01,
|
||||
0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x17, 0x0D, 0x06, 0x09, 0x13, 0x01,
|
||||
0x00, 0x22, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x17, 0x0D, 0x06,
|
||||
0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01,
|
||||
0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C,
|
||||
0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31,
|
||||
0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01,
|
||||
0x02, 0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00,
|
||||
0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03,
|
||||
0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02,
|
||||
0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D,
|
||||
0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E,
|
||||
0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00,
|
||||
0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03,
|
||||
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03,
|
||||
0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1B, 0x01, 0x01, 0x00, 0x25, 0x14,
|
||||
0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06,
|
||||
0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13,
|
||||
0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05,
|
||||
0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01,
|
||||
0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1B, 0x02, 0x00, 0x01, 0x02,
|
||||
0x0F, 0x1B, 0x01, 0x01, 0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E,
|
||||
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02,
|
||||
0x00, 0x01, 0x10, 0x0F, 0x1B, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1B, 0x02,
|
||||
0x00, 0x1B, 0x01, 0x00, 0x00, 0x00, 0x14, 0x14, 0x01, 0x80, 0x41, 0x0E,
|
||||
0x1A, 0x01, 0x80, 0x5A, 0x0B, 0x10, 0x06, 0x05, 0x01, 0x80, 0x41, 0x08,
|
||||
0x00, 0x14, 0x14, 0x01, 0x80, 0x61, 0x0E, 0x1A, 0x01, 0x80, 0x7A, 0x0B,
|
||||
0x10, 0x06, 0x05, 0x01, 0x80, 0x47, 0x08, 0x00, 0x14, 0x14, 0x01, 0x30,
|
||||
0x0E, 0x1A, 0x01, 0x39, 0x0B, 0x10, 0x06, 0x04, 0x01, 0x04, 0x07, 0x00,
|
||||
0x14, 0x01, 0x2B, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x3E, 0x00, 0x14, 0x01,
|
||||
0x2F, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x3F, 0x00, 0x01, 0x3D, 0x0C, 0x1E,
|
||||
0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x23, 0x06, 0x02, 0x04, 0x7B, 0x04,
|
||||
0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04, 0x1F, 0x01, 0x7F, 0x00,
|
||||
0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05, 0x13, 0x1F, 0x01, 0x00,
|
||||
0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00, 0x00, 0x1D, 0x04, 0x5E,
|
||||
0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x21, 0x01, 0x80, 0x7F, 0x2B, 0x14,
|
||||
0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00, 0x2C, 0x14, 0x31, 0x05,
|
||||
0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14, 0x01, 0x80, 0x61, 0x0E,
|
||||
0x1A, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03, 0x01, 0x20, 0x08, 0x00,
|
||||
0x01, 0x14, 0x03, 0x00, 0x1A, 0x17, 0x05, 0x05, 0x1F, 0x2E, 0x01, 0x00,
|
||||
0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06, 0x1F, 0x02, 0x00, 0x1A,
|
||||
0x08, 0x00, 0x2A, 0x17, 0x19, 0x1D, 0x1A, 0x1E, 0x1A, 0x04, 0x62, 0x00,
|
||||
0x18, 0x14, 0x1C, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00, 0x20,
|
||||
0x19, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04, 0x78,
|
||||
0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C, 0x06,
|
||||
0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13, 0x02,
|
||||
0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1E, 0x14, 0x21, 0x07, 0x16, 0x01,
|
||||
0x2D, 0x0C, 0x06, 0x08, 0x21, 0x07, 0x1D, 0x01, 0x00, 0x1A, 0x19, 0x00,
|
||||
0x04, 0x69, 0x21, 0x19, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1A, 0x01,
|
||||
0x20, 0x0B, 0x10, 0x00
|
||||
};
|
||||
|
||||
static const uint16_t t0_caddr[] = {
|
||||
0,
|
||||
5,
|
||||
10,
|
||||
15,
|
||||
19,
|
||||
24,
|
||||
29,
|
||||
67,
|
||||
149,
|
||||
384,
|
||||
464,
|
||||
476,
|
||||
511,
|
||||
530,
|
||||
540,
|
||||
559,
|
||||
594,
|
||||
605,
|
||||
610,
|
||||
620,
|
||||
645,
|
||||
672
|
||||
};
|
||||
|
||||
#define T0_INTERPRETED 28
|
||||
|
||||
#define T0_ENTER(ip, rp, slot) do { \
|
||||
const unsigned char *t0_newip; \
|
||||
uint32_t t0_lnum; \
|
||||
t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
|
||||
t0_lnum = t0_parse7E_unsigned(&t0_newip); \
|
||||
(rp) += t0_lnum; \
|
||||
*((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
|
||||
(ip) = t0_newip; \
|
||||
} while (0)
|
||||
|
||||
#define T0_DEFENTRY(name, slot) \
|
||||
void \
|
||||
name(void *ctx) \
|
||||
{ \
|
||||
t0_context *t0ctx = ctx; \
|
||||
t0ctx->ip = &t0_codeblock[0]; \
|
||||
T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
|
||||
}
|
||||
|
||||
T0_DEFENTRY(br_pem_decoder_init_main, 38)
|
||||
|
||||
void
|
||||
br_pem_decoder_run(void *t0ctx)
|
||||
{
|
||||
uint32_t *dp, *rp;
|
||||
const unsigned char *ip;
|
||||
|
||||
#define T0_LOCAL(x) (*(rp - 2 - (x)))
|
||||
#define T0_POP() (*-- dp)
|
||||
#define T0_POPi() (*(int32_t *)(-- dp))
|
||||
#define T0_PEEK(x) (*(dp - 1 - (x)))
|
||||
#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
|
||||
#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
|
||||
#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
|
||||
#define T0_RPOP() (*-- rp)
|
||||
#define T0_RPOPi() (*(int32_t *)(-- rp))
|
||||
#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
|
||||
#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
|
||||
#define T0_ROLL(x) do { \
|
||||
size_t t0len = (size_t)(x); \
|
||||
uint32_t t0tmp = *(dp - 1 - t0len); \
|
||||
memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
|
||||
*(dp - 1) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_SWAP() do { \
|
||||
uint32_t t0tmp = *(dp - 2); \
|
||||
*(dp - 2) = *(dp - 1); \
|
||||
*(dp - 1) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_ROT() do { \
|
||||
uint32_t t0tmp = *(dp - 3); \
|
||||
*(dp - 3) = *(dp - 2); \
|
||||
*(dp - 2) = *(dp - 1); \
|
||||
*(dp - 1) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_NROT() do { \
|
||||
uint32_t t0tmp = *(dp - 1); \
|
||||
*(dp - 1) = *(dp - 2); \
|
||||
*(dp - 2) = *(dp - 3); \
|
||||
*(dp - 3) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_PICK(x) do { \
|
||||
uint32_t t0depth = (x); \
|
||||
T0_PUSH(T0_PEEK(t0depth)); \
|
||||
} while (0)
|
||||
#define T0_CO() do { \
|
||||
goto t0_exit; \
|
||||
} while (0)
|
||||
#define T0_RET() break
|
||||
|
||||
dp = ((t0_context *)t0ctx)->dp;
|
||||
rp = ((t0_context *)t0ctx)->rp;
|
||||
ip = ((t0_context *)t0ctx)->ip;
|
||||
for (;;) {
|
||||
uint32_t t0x;
|
||||
|
||||
t0x = t0_parse7E_unsigned(&ip);
|
||||
if (t0x < T0_INTERPRETED) {
|
||||
switch (t0x) {
|
||||
int32_t t0off;
|
||||
|
||||
case 0: /* ret */
|
||||
t0x = T0_RPOP();
|
||||
rp -= (t0x >> 16);
|
||||
t0x &= 0xFFFF;
|
||||
if (t0x == 0) {
|
||||
ip = NULL;
|
||||
goto t0_exit;
|
||||
}
|
||||
ip = &t0_codeblock[t0x];
|
||||
break;
|
||||
case 1: /* literal constant */
|
||||
T0_PUSHi(t0_parse7E_signed(&ip));
|
||||
break;
|
||||
case 2: /* read local */
|
||||
T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
|
||||
break;
|
||||
case 3: /* write local */
|
||||
T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
|
||||
break;
|
||||
case 4: /* jump */
|
||||
t0off = t0_parse7E_signed(&ip);
|
||||
ip += t0off;
|
||||
break;
|
||||
case 5: /* jump if */
|
||||
t0off = t0_parse7E_signed(&ip);
|
||||
if (T0_POP()) {
|
||||
ip += t0off;
|
||||
}
|
||||
break;
|
||||
case 6: /* jump if not */
|
||||
t0off = t0_parse7E_signed(&ip);
|
||||
if (!T0_POP()) {
|
||||
ip += t0off;
|
||||
}
|
||||
break;
|
||||
case 7: {
|
||||
/* + */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a + b);
|
||||
|
||||
}
|
||||
break;
|
||||
case 8: {
|
||||
/* - */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a - b);
|
||||
|
||||
}
|
||||
break;
|
||||
case 9: {
|
||||
/* < */
|
||||
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 10: {
|
||||
/* << */
|
||||
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x << c);
|
||||
|
||||
}
|
||||
break;
|
||||
case 11: {
|
||||
/* <= */
|
||||
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 12: {
|
||||
/* <> */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a != b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 13: {
|
||||
/* = */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a == b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 14: {
|
||||
/* >= */
|
||||
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 15: {
|
||||
/* >> */
|
||||
|
||||
int c = (int)T0_POPi();
|
||||
int32_t x = T0_POPi();
|
||||
T0_PUSHi(x >> c);
|
||||
|
||||
}
|
||||
break;
|
||||
case 16: {
|
||||
/* and */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a & b);
|
||||
|
||||
}
|
||||
break;
|
||||
case 17: {
|
||||
/* co */
|
||||
T0_CO();
|
||||
}
|
||||
break;
|
||||
case 18: {
|
||||
/* data-get8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(t0_datablock[addr]);
|
||||
|
||||
}
|
||||
break;
|
||||
case 19: {
|
||||
/* drop */
|
||||
(void)T0_POP();
|
||||
}
|
||||
break;
|
||||
case 20: {
|
||||
/* dup */
|
||||
T0_PUSH(T0_PEEK(0));
|
||||
}
|
||||
break;
|
||||
case 21: {
|
||||
/* flush-buf */
|
||||
|
||||
if (CTX->ptr > 0) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 22: {
|
||||
/* get8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(*((unsigned char *)CTX + addr));
|
||||
|
||||
}
|
||||
break;
|
||||
case 23: {
|
||||
/* over */
|
||||
T0_PUSH(T0_PEEK(1));
|
||||
}
|
||||
break;
|
||||
case 24: {
|
||||
/* read8-native */
|
||||
|
||||
if (CTX->hlen > 0) {
|
||||
T0_PUSH(*CTX->hbuf ++);
|
||||
CTX->hlen --;
|
||||
} else {
|
||||
T0_PUSHi(-1);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 25: {
|
||||
/* set8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
unsigned x = T0_POP();
|
||||
*((unsigned char *)CTX + addr) = x;
|
||||
|
||||
}
|
||||
break;
|
||||
case 26: {
|
||||
/* swap */
|
||||
T0_SWAP();
|
||||
}
|
||||
break;
|
||||
case 27: {
|
||||
/* write8 */
|
||||
|
||||
unsigned char x = (unsigned char)T0_POP();
|
||||
CTX->buf[CTX->ptr ++] = x;
|
||||
if (CTX->ptr == sizeof CTX->buf) {
|
||||
if (CTX->dest) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
|
||||
}
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
T0_ENTER(ip, rp, t0x);
|
||||
}
|
||||
}
|
||||
t0_exit:
|
||||
((t0_context *)t0ctx)->dp = dp;
|
||||
((t0_context *)t0ctx)->rp = rp;
|
||||
((t0_context *)t0ctx)->ip = ip;
|
||||
}
|
||||
303
src/codec/pemdec.t0
Normal file
303
src/codec/pemdec.t0
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
\
|
||||
\ Permission is hereby granted, free of charge, to any person obtaining
|
||||
\ a copy of this software and associated documentation files (the
|
||||
\ "Software"), to deal in the Software without restriction, including
|
||||
\ without limitation the rights to use, copy, modify, merge, publish,
|
||||
\ distribute, sublicense, and/or sell copies of the Software, and to
|
||||
\ permit persons to whom the Software is furnished to do so, subject to
|
||||
\ the following conditions:
|
||||
\
|
||||
\ The above copyright notice and this permission notice shall be
|
||||
\ included in all copies or substantial portions of the Software.
|
||||
\
|
||||
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
\ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
\ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
\ SOFTWARE.
|
||||
|
||||
preamble {
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CTX ((br_pem_decoder_context *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
void
|
||||
br_pem_decoder_init(br_pem_decoder_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
ctx->cpu.dp = &ctx->dp_stack[0];
|
||||
ctx->cpu.rp = &ctx->rp_stack[0];
|
||||
br_pem_decoder_init_main(&ctx->cpu);
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
size_t
|
||||
br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (ctx->event) {
|
||||
return 0;
|
||||
}
|
||||
ctx->hbuf = data;
|
||||
ctx->hlen = len;
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
return len - ctx->hlen;
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
int
|
||||
br_pem_decoder_event(br_pem_decoder_context *ctx)
|
||||
{
|
||||
int event;
|
||||
|
||||
event = ctx->event;
|
||||
ctx->event = 0;
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
\ Define a word that evaluates to the address of a field within the
|
||||
\ decoder context.
|
||||
: addr:
|
||||
next-word { field }
|
||||
"addr-" field + 0 1 define-word
|
||||
0 8191 "offsetof(br_pem_decoder_context, " field + ")" + make-CX
|
||||
postpone literal postpone ; ;
|
||||
|
||||
addr: event
|
||||
addr: name
|
||||
addr: buf
|
||||
addr: ptr
|
||||
|
||||
\ Set a byte at a specific address (offset within the context).
|
||||
cc: set8 ( value addr -- ) {
|
||||
size_t addr = T0_POP();
|
||||
unsigned x = T0_POP();
|
||||
*((unsigned char *)CTX + addr) = x;
|
||||
}
|
||||
|
||||
\ Get a byte at a specific address (offset within the context).
|
||||
cc: get8 ( addr -- value ) {
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(*((unsigned char *)CTX + addr));
|
||||
}
|
||||
|
||||
\ Send an event.
|
||||
: send-event ( event -- )
|
||||
addr-event set8 co ;
|
||||
|
||||
\ Low-level function to read a single byte. Returned value is the byte
|
||||
\ (0 to 255), or -1 if there is no available data.
|
||||
cc: read8-native ( -- x ) {
|
||||
if (CTX->hlen > 0) {
|
||||
T0_PUSH(*CTX->hbuf ++);
|
||||
CTX->hlen --;
|
||||
} else {
|
||||
T0_PUSHi(-1);
|
||||
}
|
||||
}
|
||||
|
||||
\ Read next byte. Block until the next byte is available.
|
||||
: read8 ( -- x )
|
||||
begin read8-native dup 0< ifnot ret then drop co again ;
|
||||
|
||||
\ Read bytes until next end-of-line.
|
||||
: skip-newline ( -- )
|
||||
begin read8 `\n <> while repeat ;
|
||||
|
||||
\ Read bytes until next end-of-line; verify that they are all whitespace.
|
||||
\ This returns -1 if they were all whitespace, 0 otherwise.
|
||||
: skip-newline-ws ( -- bool )
|
||||
-1 { r }
|
||||
begin read8 dup `\n <> while ws? ifnot 0 >r then repeat
|
||||
drop r ;
|
||||
|
||||
\ Normalise a byte to uppercase (ASCII only).
|
||||
: norm-upper ( x -- x )
|
||||
dup dup `a >= swap `z <= and if 32 - then ;
|
||||
|
||||
\ Read bytes and compare with the provided string. On mismatch, the
|
||||
\ rest of the line is consumed. Matching is not case sensitive.
|
||||
: match-string ( str -- bool )
|
||||
begin
|
||||
dup data-get8 norm-upper dup ifnot 2drop -1 ret then
|
||||
read8 norm-upper dup `\n = if drop 2drop 0 ret then
|
||||
= ifnot drop skip-newline 0 ret then
|
||||
1+
|
||||
again ;
|
||||
|
||||
\ Read bytes into the provided buffer, but no more than the provided
|
||||
\ count. Reading stops when end-of-line is reached. Returned value
|
||||
\ is the count of bytes written to the buffer, or 0 if the buffer size
|
||||
\ was exceeded. All bytes are normalised to uppercase (ASCII only).
|
||||
: read-bytes ( addr len -- len )
|
||||
dup { orig-len }
|
||||
swap
|
||||
begin
|
||||
over ifnot 2drop skip-newline 0 ret then
|
||||
read8 dup `\n = if 2drop orig-len swap - ret then
|
||||
norm-upper over set8 1+ swap 1- swap
|
||||
again ;
|
||||
|
||||
\ Remove trailing dashes from the name buffer.
|
||||
: trim-dashes ( len -- )
|
||||
begin dup while
|
||||
1-
|
||||
dup addr-name + get8 `- <> if
|
||||
addr-name + 1+ 0 swap set8 ret
|
||||
then
|
||||
repeat
|
||||
addr-name set8 ;
|
||||
|
||||
\ Scan input for next "begin" banner.
|
||||
: next-banner-begin ( -- )
|
||||
begin
|
||||
"-----BEGIN " match-string if
|
||||
addr-name 127 read-bytes
|
||||
dup if trim-dashes ret then
|
||||
drop
|
||||
then
|
||||
again ;
|
||||
|
||||
\ Convert a Base64 character to its numerical value. Returned value is
|
||||
\ 0 to 63 for Base64 characters, -1 for '=', and -2 for all other characters.
|
||||
: from-base64 ( char -- x )
|
||||
dup dup `A >= swap `Z <= and if 65 - ret then
|
||||
dup dup `a >= swap `z <= and if 71 - ret then
|
||||
dup dup `0 >= swap `9 <= and if 4 + ret then
|
||||
dup `+ = if drop 62 ret then
|
||||
dup `/ = if drop 63 ret then
|
||||
`= <> 1- ;
|
||||
|
||||
\ Test whether a character is whitespace (but not a newline).
|
||||
: ws? ( x -- bool )
|
||||
dup `\n <> swap 32 <= and ;
|
||||
|
||||
\ Read next character, skipping whitespace (except newline).
|
||||
: next-nonws ( -- x )
|
||||
begin
|
||||
read8 dup ws? ifnot ret then
|
||||
drop
|
||||
again ;
|
||||
|
||||
\ Write one byte in the output buffer.
|
||||
cc: write8 ( x -- ) {
|
||||
unsigned char x = (unsigned char)T0_POP();
|
||||
CTX->buf[CTX->ptr ++] = x;
|
||||
if (CTX->ptr == sizeof CTX->buf) {
|
||||
if (CTX->dest) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
|
||||
}
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
\ Flush the output buffer.
|
||||
cc: flush-buf ( -- ) {
|
||||
if (CTX->ptr > 0) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
\ Decode the four next Base64 characters. Returned value is:
|
||||
\ 0 quartet processed, three bytes produced.
|
||||
\ -1 dash encountered as first character (no leading whitespace).
|
||||
\ 1 quartet processed, one or two bytes produced, terminator reached.
|
||||
\ 2 end-of-line reached.
|
||||
\ 3 error.
|
||||
\ For all positive return values, the remaining of the current line has been
|
||||
\ consumed.
|
||||
: decode-next-quartet ( -- r )
|
||||
\ Process first character. It may be a dash.
|
||||
read8 dup `- = if drop -1 ret then
|
||||
dup ws? if drop next-nonws then
|
||||
dup `\n = if drop 2 ret then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
{ acc }
|
||||
|
||||
\ Second character.
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
acc 6 << + >acc
|
||||
|
||||
\ Third character: may be an equal sign.
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
dup `= = if
|
||||
\ Fourth character must be an equal sign.
|
||||
drop
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
skip-newline-ws ifnot drop 3 ret then
|
||||
`= <> if 3 ret then
|
||||
acc 0x0F and if 3 ret then
|
||||
acc 4 >> write8
|
||||
1 ret
|
||||
then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
acc 6 << + >acc
|
||||
|
||||
\ Fourth character: may be an equal sign.
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
dup `= = if
|
||||
drop skip-newline-ws ifnot 3 ret then
|
||||
acc 0x03 and if 3 ret then
|
||||
acc 10 >> write8
|
||||
acc 2 >> write8
|
||||
1 ret
|
||||
then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
acc 6 << + >acc
|
||||
acc 16 >> write8
|
||||
acc 8 >> write8
|
||||
acc write8
|
||||
0 ;
|
||||
|
||||
\ Check trailer line (possibly, the leading dash has been read). This
|
||||
\ sends the appropriate event.
|
||||
: check-trailer ( bool -- )
|
||||
ifnot
|
||||
begin read8 dup `\n = while drop repeat
|
||||
`- <> if skip-newline 3 send-event ret then
|
||||
then
|
||||
"----END " match-string ifnot 3 send-event ret then
|
||||
flush-buf
|
||||
skip-newline 2 send-event ;
|
||||
|
||||
\ Decode one line worth of characters. Returned value is 0 if the end of the
|
||||
\ object is reached, -1 otherwise. The end of object or error event is sent.
|
||||
: decode-line ( -- bool )
|
||||
-1 { first }
|
||||
begin
|
||||
decode-next-quartet
|
||||
case
|
||||
0 of endof
|
||||
-1 of
|
||||
first ifnot
|
||||
skip-newline 3 send-event
|
||||
else
|
||||
-1 check-trailer
|
||||
then
|
||||
0 ret
|
||||
endof
|
||||
1 of 0 check-trailer 0 ret endof
|
||||
2 of -1 ret endof
|
||||
|
||||
\ On decoding error
|
||||
drop 3 send-event 0 ret
|
||||
endcase
|
||||
0 >first
|
||||
again ;
|
||||
|
||||
: main ( -- ! )
|
||||
begin
|
||||
next-banner-begin 1 send-event
|
||||
begin decode-line while repeat
|
||||
again ;
|
||||
102
src/config.h
Normal file
102
src/config.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H__
|
||||
#define CONFIG_H__
|
||||
|
||||
/*
|
||||
* This file contains compile-time flags that can override the
|
||||
* autodetection performed in relevant files. Each flag is a macro; it
|
||||
* deactivates the feature if defined to 0, activates it if defined to a
|
||||
* non-zero integer (normally 1). If the macro is not defined, then
|
||||
* autodetection applies.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_64 is enabled, 64-bit integer types are assumed to be
|
||||
* efficient (i.e. the architecture has 64-bit registers and can
|
||||
* do 64-bit operations as fast as 32-bit operations).
|
||||
*
|
||||
#define BR_64 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_SLOW_MUL is enabled, multiplications are assumed to be
|
||||
* substantially slow with regards to other integer operations, thus
|
||||
* making it worth to make more operations for a given task if it allows
|
||||
* using less multiplications.
|
||||
*
|
||||
#define BR_SLOW_MUL 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used
|
||||
* in the "i31" big integer implementation) use an alternate implementation
|
||||
* which is slower and larger than the normal multiplication, but should
|
||||
* ensure constant-time multiplications even on architectures where the
|
||||
* multiplication opcode takes a variable number of cycles to complete.
|
||||
*
|
||||
#define BR_CT_MUL31 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom
|
||||
* to automatically obtain quality randomness for seedings its internal
|
||||
* PRNG.
|
||||
*
|
||||
#define BR_USE_URANDOM 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32
|
||||
* (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to
|
||||
* automatically obtain quality randomness for seedings its internal PRNG.
|
||||
*
|
||||
* Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the
|
||||
* former takes precedence.
|
||||
*
|
||||
#define BR_USE_WIN32_RAND 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains
|
||||
* the current time from the OS by calling time(), and assuming that the
|
||||
* returned value (a 'time_t') is an integer that counts time in seconds
|
||||
* since the Unix Epoch (Jan 1st, 1970, 00:00 UTC).
|
||||
*
|
||||
#define BR_USE_UNIX_TIME 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains
|
||||
* the current time from the OS by calling the Win32 function
|
||||
* GetSystemTimeAsFileTime().
|
||||
*
|
||||
* Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the
|
||||
* former takes precedence.
|
||||
*
|
||||
#define BR_USE_WIN32_TIME 1
|
||||
*/
|
||||
|
||||
#endif
|
||||
791
src/ec/ec_prime_i31.c
Normal file
791
src/ec/ec_prime_i31.c
Normal file
|
|
@ -0,0 +1,791 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for supported curves (field modulus, and 'b' equation
|
||||
* parameter; both values use the 'i31' format, and 'b' is in Montgomery
|
||||
* representation).
|
||||
*/
|
||||
|
||||
static const uint32_t P256_P[] = {
|
||||
0x00000108,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
|
||||
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
|
||||
0x000000FF
|
||||
};
|
||||
|
||||
static const uint32_t P256_R2[] = {
|
||||
0x00000108,
|
||||
0x00014000, 0x00018000, 0x00000000, 0x7FF40000,
|
||||
0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P256_B[] = {
|
||||
0x00000108,
|
||||
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
|
||||
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
|
||||
0x0000000E
|
||||
};
|
||||
|
||||
static const uint32_t P384_P[] = {
|
||||
0x0000018C,
|
||||
0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
|
||||
0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x00000FFF
|
||||
};
|
||||
|
||||
static const uint32_t P384_R2[] = {
|
||||
0x0000018C,
|
||||
0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF,
|
||||
0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF,
|
||||
0x00008000, 0x00008000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P384_B[] = {
|
||||
0x0000018C,
|
||||
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
|
||||
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
|
||||
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
|
||||
0x000008A5
|
||||
};
|
||||
|
||||
static const uint32_t P521_P[] = {
|
||||
0x00000219,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x01FFFFFF
|
||||
};
|
||||
|
||||
static const uint32_t P521_R2[] = {
|
||||
0x00000219,
|
||||
0x00001000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P521_B[] = {
|
||||
0x00000219,
|
||||
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
|
||||
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
|
||||
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
|
||||
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
|
||||
0x00654FAE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint32_t *p;
|
||||
const uint32_t *b;
|
||||
const uint32_t *R2;
|
||||
uint32_t p0i;
|
||||
} curve_params;
|
||||
|
||||
static inline const curve_params *
|
||||
id_to_curve(int curve)
|
||||
{
|
||||
static const curve_params pp[] = {
|
||||
{ P256_P, P256_B, P256_R2, 0x00000001 },
|
||||
{ P384_P, P384_B, P384_R2, 0x00000001 },
|
||||
{ P521_P, P521_B, P521_R2, 0x00000001 }
|
||||
};
|
||||
|
||||
return &pp[curve - BR_EC_secp256r1];
|
||||
}
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
|
||||
/*
|
||||
* Type for a point in Jacobian coordinates:
|
||||
* -- three values, x, y and z, in Montgomery representation
|
||||
* -- affine coordinates are X = x / z^2 and Y = y / z^3
|
||||
* -- for the point at infinity, z = 0
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t c[3][I31_LEN];
|
||||
} jacobian;
|
||||
|
||||
/*
|
||||
* We use a custom interpreter that uses a dozen registers, and
|
||||
* only four operations:
|
||||
* MSET(d, a) copy a into d
|
||||
* MADD(d, a) d = d+a (modular)
|
||||
* MSUB(d, a) d = d-a (modular)
|
||||
* MMUL(d, a, b) d = a*b (Montgomery multiplication)
|
||||
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
|
||||
* MTZ(d) clear return value if d = 0
|
||||
* Destination of MMUL (d) must be distinct from operands (a and b).
|
||||
* There is no such constraint for MSUB and MADD.
|
||||
*
|
||||
* Registers include the operand coordinates, and temporaries.
|
||||
*/
|
||||
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
|
||||
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
|
||||
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
|
||||
#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MTZ(d) (0x5000 + ((d) << 8))
|
||||
#define ENDCODE 0
|
||||
|
||||
/*
|
||||
* Registers for the input operands.
|
||||
*/
|
||||
#define P1x 0
|
||||
#define P1y 1
|
||||
#define P1z 2
|
||||
#define P2x 3
|
||||
#define P2y 4
|
||||
#define P2z 5
|
||||
|
||||
/*
|
||||
* Alternate names for the first input operand.
|
||||
*/
|
||||
#define Px 0
|
||||
#define Py 1
|
||||
#define Pz 2
|
||||
|
||||
/*
|
||||
* Temporaries.
|
||||
*/
|
||||
#define t1 6
|
||||
#define t2 7
|
||||
#define t3 8
|
||||
#define t4 9
|
||||
#define t5 10
|
||||
#define t6 11
|
||||
#define t7 12
|
||||
|
||||
/*
|
||||
* Extra scratch registers available when there is no second operand (e.g.
|
||||
* for "double" and "affine").
|
||||
*/
|
||||
#define t8 3
|
||||
#define t9 4
|
||||
#define t10 5
|
||||
|
||||
/*
|
||||
* Doubling formulas are:
|
||||
*
|
||||
* s = 4*x*y^2
|
||||
* m = 3*(x + z^2)*(x - z^2)
|
||||
* x' = m^2 - 2*s
|
||||
* y' = m*(s - x') - 8*y^4
|
||||
* z' = 2*y*z
|
||||
*
|
||||
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
|
||||
* should. This case should not happen anyway, because our curves have
|
||||
* prime order, and thus do not contain any point of order 2.
|
||||
*
|
||||
* If P is infinity (z = 0), then again the formulas yield infinity,
|
||||
* which is correct. Thus, this code works for all points.
|
||||
*
|
||||
* Cost: 8 multiplications
|
||||
*/
|
||||
static const uint16_t code_double[] = {
|
||||
/*
|
||||
* Compute z^2 (in t1).
|
||||
*/
|
||||
MMUL(t1, Pz, Pz),
|
||||
|
||||
/*
|
||||
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
|
||||
*/
|
||||
MSET(t2, Px),
|
||||
MSUB(t2, t1),
|
||||
MADD(t1, Px),
|
||||
|
||||
/*
|
||||
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
|
||||
*/
|
||||
MMUL(t3, t1, t2),
|
||||
MSET(t1, t3),
|
||||
MADD(t1, t3),
|
||||
MADD(t1, t3),
|
||||
|
||||
/*
|
||||
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
|
||||
*/
|
||||
MMUL(t3, Py, Py),
|
||||
MADD(t3, t3),
|
||||
MMUL(t2, Px, t3),
|
||||
MADD(t2, t2),
|
||||
|
||||
/*
|
||||
* Compute x' = m^2 - 2*s.
|
||||
*/
|
||||
MMUL(Px, t1, t1),
|
||||
MSUB(Px, t2),
|
||||
MSUB(Px, t2),
|
||||
|
||||
/*
|
||||
* Compute z' = 2*y*z.
|
||||
*/
|
||||
MMUL(t4, Py, Pz),
|
||||
MSET(Pz, t4),
|
||||
MADD(Pz, t4),
|
||||
|
||||
/*
|
||||
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
|
||||
* 2*y^2 in t3.
|
||||
*/
|
||||
MSUB(t2, Px),
|
||||
MMUL(Py, t1, t2),
|
||||
MMUL(t4, t3, t3),
|
||||
MSUB(Py, t4),
|
||||
MSUB(Py, t4),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Addtions formulas are:
|
||||
*
|
||||
* u1 = x1 * z2^2
|
||||
* u2 = x2 * z1^2
|
||||
* s1 = y1 * z2^3
|
||||
* s2 = y2 * z1^3
|
||||
* h = u2 - u1
|
||||
* r = s2 - s1
|
||||
* x3 = r^2 - h^3 - 2 * u1 * h^2
|
||||
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
|
||||
* z3 = h * z1 * z2
|
||||
*
|
||||
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
|
||||
* z3 == 0, so the result is correct.
|
||||
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
|
||||
* not correct.
|
||||
* h == 0 only if u1 == u2; this happens in two cases:
|
||||
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
|
||||
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
|
||||
*
|
||||
* Thus, the following situations are not handled correctly:
|
||||
* -- P1 = 0 and P2 != 0
|
||||
* -- P1 != 0 and P2 = 0
|
||||
* -- P1 = P2
|
||||
* All other cases are properly computed. However, even in "incorrect"
|
||||
* situations, the three coordinates still are properly formed field
|
||||
* elements.
|
||||
*
|
||||
* The returned flag is cleared if r == 0. This happens in the following
|
||||
* cases:
|
||||
* -- Both points are on the same horizontal line (same Y coordinate).
|
||||
* -- Both points are infinity.
|
||||
* -- One point is infinity and the other is on line Y = 0.
|
||||
* The third case cannot happen with our curves (there is no valid point
|
||||
* on line Y = 0 since that would be a point of order 2). If the two
|
||||
* source points are non-infinity, then remains only the case where the
|
||||
* two points are on the same horizontal line.
|
||||
*
|
||||
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
|
||||
* P2 != 0:
|
||||
* -- If the returned value is not the point at infinity, then it was properly
|
||||
* computed.
|
||||
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
|
||||
* is indeed the point at infinity.
|
||||
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
|
||||
* use the 'double' code.
|
||||
*
|
||||
* Cost: 16 multiplications
|
||||
*/
|
||||
static const uint16_t code_add[] = {
|
||||
/*
|
||||
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
|
||||
*/
|
||||
MMUL(t3, P2z, P2z),
|
||||
MMUL(t1, P1x, t3),
|
||||
MMUL(t4, P2z, t3),
|
||||
MMUL(t3, P1y, t4),
|
||||
|
||||
/*
|
||||
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
|
||||
*/
|
||||
MMUL(t4, P1z, P1z),
|
||||
MMUL(t2, P2x, t4),
|
||||
MMUL(t5, P1z, t4),
|
||||
MMUL(t4, P2y, t5),
|
||||
|
||||
/*
|
||||
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
|
||||
*/
|
||||
MSUB(t2, t1),
|
||||
MSUB(t4, t3),
|
||||
|
||||
/*
|
||||
* Report cases where r = 0 through the returned flag.
|
||||
*/
|
||||
MTZ(t4),
|
||||
|
||||
/*
|
||||
* Compute u1*h^2 (in t6) and h^3 (in t5).
|
||||
*/
|
||||
MMUL(t7, t2, t2),
|
||||
MMUL(t6, t1, t7),
|
||||
MMUL(t5, t7, t2),
|
||||
|
||||
/*
|
||||
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
|
||||
* t1 and t7 can be used as scratch registers.
|
||||
*/
|
||||
MMUL(P1x, t4, t4),
|
||||
MSUB(P1x, t5),
|
||||
MSUB(P1x, t6),
|
||||
MSUB(P1x, t6),
|
||||
|
||||
/*
|
||||
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
|
||||
*/
|
||||
MSUB(t6, P1x),
|
||||
MMUL(P1y, t4, t6),
|
||||
MMUL(t1, t5, t3),
|
||||
MSUB(P1y, t1),
|
||||
|
||||
/*
|
||||
* Compute z3 = h*z1*z2.
|
||||
*/
|
||||
MMUL(t1, P1z, P2z),
|
||||
MMUL(P1z, t1, t2),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Check that the point is on the curve. This code snippet assumes the
|
||||
* following conventions:
|
||||
* -- Coordinates x and y have been freshly decoded in P1 (but not
|
||||
* converted to Montgomery coordinates yet).
|
||||
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
|
||||
*/
|
||||
static const uint16_t code_check[] = {
|
||||
|
||||
/* Convert x and y to Montgomery representation. */
|
||||
MMUL(t1, P1x, P2x),
|
||||
MMUL(t2, P1y, P2x),
|
||||
MSET(P1x, t1),
|
||||
MSET(P1y, t2),
|
||||
|
||||
/* Compute x^3 in t1. */
|
||||
MMUL(t2, P1x, P1x),
|
||||
MMUL(t1, P1x, t2),
|
||||
|
||||
/* Subtract 3*x from t1. */
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
|
||||
/* Add b. */
|
||||
MADD(t1, P2y),
|
||||
|
||||
/* Compute y^2 in t2. */
|
||||
MMUL(t2, P1y, P1y),
|
||||
|
||||
/* Compare y^2 with x^3 - 3*x + b; they must match. */
|
||||
MSUB(t1, t2),
|
||||
MTZ(t1),
|
||||
|
||||
/* Set z to 1 (in Montgomery representation). */
|
||||
MMUL(P1z, P2x, P2z),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversion back to affine coordinates. This code snippet assumes that
|
||||
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
|
||||
*/
|
||||
static const uint16_t code_affine[] = {
|
||||
|
||||
/* Save z*R in t1. */
|
||||
MSET(t1, P1z),
|
||||
|
||||
/* Compute z^3 in t2. */
|
||||
MMUL(t2, P1z, P1z),
|
||||
MMUL(t3, P1z, t2),
|
||||
MMUL(t2, t3, P2z),
|
||||
|
||||
/* Invert to (1/z^3) in t2. */
|
||||
MINV(t2, t3, t4),
|
||||
|
||||
/* Compute y. */
|
||||
MSET(t3, P1y),
|
||||
MMUL(P1y, t2, t3),
|
||||
|
||||
/* Compute (1/z^2) in t3. */
|
||||
MMUL(t3, t2, t1),
|
||||
|
||||
/* Compute x. */
|
||||
MSET(t2, P1x),
|
||||
MMUL(P1x, t2, t3),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
run_code(jacobian *P1, const jacobian *P2,
|
||||
const curve_params *cc, const uint16_t *code)
|
||||
{
|
||||
uint32_t r;
|
||||
uint32_t t[13][I31_LEN];
|
||||
size_t u;
|
||||
|
||||
r = 1;
|
||||
|
||||
/*
|
||||
* Copy the two operands in the dedicated registers.
|
||||
*/
|
||||
memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t));
|
||||
memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t));
|
||||
|
||||
/*
|
||||
* Run formulas.
|
||||
*/
|
||||
for (u = 0;; u ++) {
|
||||
unsigned op, d, a, b;
|
||||
|
||||
op = code[u];
|
||||
if (op == 0) {
|
||||
break;
|
||||
}
|
||||
d = (op >> 8) & 0x0F;
|
||||
a = (op >> 4) & 0x0F;
|
||||
b = op & 0x0F;
|
||||
op >>= 12;
|
||||
switch (op) {
|
||||
uint32_t ctl;
|
||||
size_t plen;
|
||||
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
|
||||
case 0:
|
||||
memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t));
|
||||
break;
|
||||
case 1:
|
||||
ctl = br_i31_add(t[d], t[a], 1);
|
||||
ctl |= NOT(br_i31_sub(t[d], cc->p, 0));
|
||||
br_i31_sub(t[d], cc->p, ctl);
|
||||
break;
|
||||
case 2:
|
||||
br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1));
|
||||
break;
|
||||
case 3:
|
||||
br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
|
||||
break;
|
||||
case 4:
|
||||
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
|
||||
br_i31_encode(tp, plen, cc->p);
|
||||
tp[plen - 1] -= 2;
|
||||
br_i31_modpow(t[d], tp, plen,
|
||||
cc->p, cc->p0i, t[a], t[b]);
|
||||
break;
|
||||
default:
|
||||
r &= ~br_i31_iszero(t[d]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy back result.
|
||||
*/
|
||||
memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
set_one(uint32_t *x, const uint32_t *p)
|
||||
{
|
||||
size_t plen;
|
||||
|
||||
plen = (p[0] + 63) >> 5;
|
||||
memset(x, 0, plen * sizeof *x);
|
||||
x[0] = p[0];
|
||||
x[1] = 0x00000001;
|
||||
}
|
||||
|
||||
static void
|
||||
point_zero(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
memset(P, 0, sizeof *P);
|
||||
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_double(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
run_code(P, P, cc, code_double);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
|
||||
{
|
||||
return run_code(P1, P2, cc, code_add);
|
||||
}
|
||||
|
||||
static void
|
||||
point_mul(jacobian *P, const unsigned char *x, size_t xlen,
|
||||
const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* We do a simple double-and-add ladder with a 2-bit window
|
||||
* to make only one add every two doublings. We thus first
|
||||
* precompute 2P and 3P in some local buffers.
|
||||
*
|
||||
* We always perform two doublings and one addition; the
|
||||
* addition is with P, 2P and 3P and is done in a temporary
|
||||
* array.
|
||||
*
|
||||
* The addition code cannot handle cases where one of the
|
||||
* operands is infinity, which is the case at the start of the
|
||||
* ladder. We therefore need to maintain a flag that controls
|
||||
* this situation.
|
||||
*/
|
||||
uint32_t qz;
|
||||
jacobian P2, P3, Q, T, U;
|
||||
|
||||
memcpy(&P2, P, sizeof P2);
|
||||
point_double(&P2, cc);
|
||||
memcpy(&P3, P, sizeof P3);
|
||||
point_add(&P3, &P2, cc);
|
||||
|
||||
point_zero(&Q, cc);
|
||||
qz = 1;
|
||||
while (xlen -- > 0) {
|
||||
int k;
|
||||
|
||||
for (k = 6; k >= 0; k -= 2) {
|
||||
uint32_t bits;
|
||||
uint32_t bnz;
|
||||
|
||||
point_double(&Q, cc);
|
||||
point_double(&Q, cc);
|
||||
memcpy(&T, P, sizeof T);
|
||||
memcpy(&U, &Q, sizeof U);
|
||||
bits = (*x >> k) & (uint32_t)3;
|
||||
bnz = NEQ(bits, 0);
|
||||
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
|
||||
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
|
||||
point_add(&U, &T, cc);
|
||||
CCOPY(bnz & qz, &Q, &T, sizeof Q);
|
||||
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
|
||||
qz &= ~bnz;
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
memcpy(P, &Q, sizeof Q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode point into Jacobian coordinates. This function does not support
|
||||
* the point at infinity. If the point is invalid then this returns 0, but
|
||||
* the coordinates are still set to properly formed field elements.
|
||||
*/
|
||||
static uint32_t
|
||||
point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* Points must use uncompressed format:
|
||||
* -- first byte is 0x04;
|
||||
* -- coordinates X and Y use unsigned big-endian, with the same
|
||||
* length as the field modulus.
|
||||
*
|
||||
* We don't support hybrid format (uncompressed, but first byte
|
||||
* has value 0x06 or 0x07, depending on the least significant bit
|
||||
* of Y) because it is rather useless, and explicitly forbidden
|
||||
* by PKIX (RFC 5480, section 2.2).
|
||||
*
|
||||
* We don't support compressed format either, because it is not
|
||||
* much used in practice (there are or were patent-related
|
||||
* concerns about point compression, which explains the lack of
|
||||
* generalised support). Also, point compression support would
|
||||
* need a bit more code.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t plen, zlen;
|
||||
uint32_t r;
|
||||
jacobian Q;
|
||||
|
||||
buf = src;
|
||||
point_zero(P, cc);
|
||||
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
|
||||
if (len != 1 + (plen << 1)) {
|
||||
return 0;
|
||||
}
|
||||
r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p);
|
||||
r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
|
||||
|
||||
/*
|
||||
* Check first byte.
|
||||
*/
|
||||
r &= EQ(buf[0], 0x04);
|
||||
/* obsolete
|
||||
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
|
||||
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert coordinates and check that the point is valid.
|
||||
*/
|
||||
zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t);
|
||||
memcpy(Q.c[0], cc->R2, zlen);
|
||||
memcpy(Q.c[1], cc->b, zlen);
|
||||
set_one(Q.c[2], cc->p);
|
||||
r &= ~run_code(P, &Q, cc, code_check);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a point. This method assumes that the point is correct and is
|
||||
* not the point at infinity. Encoded size is always 1+2*plen, where
|
||||
* plen is the field modulus length, in bytes.
|
||||
*/
|
||||
static void
|
||||
point_encode(void *dst, const jacobian *P, const curve_params *cc)
|
||||
{
|
||||
unsigned char *buf;
|
||||
uint32_t xbl;
|
||||
size_t plen;
|
||||
jacobian Q, T;
|
||||
|
||||
buf = dst;
|
||||
xbl = cc->p[0];
|
||||
xbl -= (xbl >> 5);
|
||||
plen = (xbl + 7) >> 3;
|
||||
buf[0] = 0x04;
|
||||
memcpy(&Q, P, sizeof *P);
|
||||
set_one(T.c[2], cc->p);
|
||||
run_code(&Q, &T, cc, code_affine);
|
||||
br_i31_encode(buf + 1, plen, Q.c[0]);
|
||||
br_i31_encode(buf + 1 + plen, plen, Q.c[1]);
|
||||
}
|
||||
|
||||
static const br_ec_curve_def *
|
||||
id_to_curve_def(int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return &br_secp256r1;
|
||||
case BR_EC_secp384r1:
|
||||
return &br_secp384r1;
|
||||
case BR_EC_secp521r1:
|
||||
return &br_secp521r1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->generator_len;
|
||||
return cd->generator;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->order_len;
|
||||
return cd->order;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
uint32_t r;
|
||||
const curve_params *cc;
|
||||
jacobian P;
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, G, Glen, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_encode(G, &P, cc);
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
uint32_t r, t, z;
|
||||
const curve_params *cc;
|
||||
jacobian P, Q;
|
||||
|
||||
/*
|
||||
* TODO: see about merging the two ladders. Right now, we do
|
||||
* two independant point multiplications, which is a bit
|
||||
* wasteful of CPU resources (but yields short code).
|
||||
*/
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, A, len, cc);
|
||||
r &= point_decode(&Q, B, len, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_mul(&Q, y, ylen, cc);
|
||||
|
||||
/*
|
||||
* We want to compute P+Q. Since the base points A and B are distinct
|
||||
* from infinity, and the multipliers are non-zero and lower than the
|
||||
* curve order, then we know that P and Q are non-infinity. This
|
||||
* leaves two special situations to test for:
|
||||
* -- If P = Q then we must use point_double().
|
||||
* -- If P+Q = 0 then we must report an error.
|
||||
*/
|
||||
t = point_add(&P, &Q, cc);
|
||||
point_double(&Q, cc);
|
||||
z = br_i31_iszero(P.c[2]);
|
||||
|
||||
/*
|
||||
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
|
||||
* have the following:
|
||||
*
|
||||
* z = 0, t = 0 return P (normal addition)
|
||||
* z = 0, t = 1 return P (normal addition)
|
||||
* z = 1, t = 0 return Q (a 'double' case)
|
||||
* z = 1, t = 1 report an error (P+Q = 0)
|
||||
*/
|
||||
CCOPY(z & ~t, &P, &Q, sizeof Q);
|
||||
point_encode(A, &P, cc);
|
||||
r &= ~(z & t);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_prime_i31 = {
|
||||
(uint32_t)0x03800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_mul,
|
||||
&api_muladd
|
||||
};
|
||||
46
src/ec/ec_prime_i31_secp256r1.c
Normal file
46
src/ec/ec_prime_i31_secp256r1.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const uint32_t P256_P[] = {
|
||||
0x00000108,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
|
||||
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
|
||||
0x000000FF
|
||||
};
|
||||
|
||||
static const uint32_t P256_B[] = {
|
||||
0x00000108,
|
||||
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
|
||||
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
|
||||
0x0000000E
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp256r1 = {
|
||||
P256_P,
|
||||
P256_B,
|
||||
0x00000001
|
||||
};
|
||||
48
src/ec/ec_prime_i31_secp384r1.c
Normal file
48
src/ec/ec_prime_i31_secp384r1.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const uint32_t P384_P[] = {
|
||||
0x0000018C,
|
||||
0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
|
||||
0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x00000FFF
|
||||
};
|
||||
|
||||
static const uint32_t P384_B[] = {
|
||||
0x0000018C,
|
||||
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
|
||||
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
|
||||
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
|
||||
0x000008A5
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp384r1 = {
|
||||
P384_P,
|
||||
P384_B,
|
||||
0x00000001
|
||||
};
|
||||
50
src/ec/ec_prime_i31_secp521r1.c
Normal file
50
src/ec/ec_prime_i31_secp521r1.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const uint32_t P521_P[] = {
|
||||
0x00000219,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x01FFFFFF
|
||||
};
|
||||
|
||||
static const uint32_t P521_B[] = {
|
||||
0x00000219,
|
||||
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
|
||||
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
|
||||
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
|
||||
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
|
||||
0x00654FAE
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp521r1 = {
|
||||
P521_P,
|
||||
P521_B,
|
||||
0x00000001
|
||||
};
|
||||
51
src/ec/ec_secp256r1.c
Normal file
51
src/ec/ec_secp256r1.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P256_N[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
|
||||
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
|
||||
};
|
||||
|
||||
static const unsigned char P256_G[] = {
|
||||
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42,
|
||||
0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40,
|
||||
0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33,
|
||||
0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
|
||||
0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
|
||||
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E,
|
||||
0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E,
|
||||
0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51,
|
||||
0xF5
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp256r1 = {
|
||||
BR_EC_secp256r1,
|
||||
P256_N, sizeof P256_N,
|
||||
P256_G, sizeof P256_G
|
||||
};
|
||||
57
src/ec/ec_secp384r1.c
Normal file
57
src/ec/ec_secp384r1.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P384_N[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF,
|
||||
0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A,
|
||||
0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
|
||||
};
|
||||
|
||||
static const unsigned char P384_G[] = {
|
||||
0x04, 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05,
|
||||
0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD,
|
||||
0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B,
|
||||
0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A,
|
||||
0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29,
|
||||
0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A,
|
||||
0xB7, 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C,
|
||||
0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC,
|
||||
0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14,
|
||||
0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8,
|
||||
0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81,
|
||||
0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E,
|
||||
0x5F
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp384r1 = {
|
||||
BR_EC_secp384r1,
|
||||
P384_N, sizeof P384_N,
|
||||
P384_G, sizeof P384_G
|
||||
};
|
||||
64
src/ec/ec_secp521r1.c
Normal file
64
src/ec/ec_secp521r1.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P521_N[] = {
|
||||
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
|
||||
0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
|
||||
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
|
||||
0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
|
||||
0x64, 0x09
|
||||
};
|
||||
|
||||
static const unsigned char P521_G[] = {
|
||||
0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04,
|
||||
0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23,
|
||||
0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05,
|
||||
0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B,
|
||||
0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF,
|
||||
0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2,
|
||||
0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85,
|
||||
0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2,
|
||||
0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6A,
|
||||
0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F,
|
||||
0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44,
|
||||
0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD,
|
||||
0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72,
|
||||
0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9,
|
||||
0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70,
|
||||
0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94,
|
||||
0x76, 0x9F, 0xD1, 0x66, 0x50
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp521r1 = {
|
||||
BR_EC_secp521r1,
|
||||
P521_N, sizeof P521_N,
|
||||
P521_G, sizeof P521_G
|
||||
};
|
||||
102
src/ec/ecdsa_atr.c
Normal file
102
src/ec/ecdsa_atr.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_asn1_to_raw(void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* Note: this code is a bit lenient in that it accepts a few
|
||||
* deviations to DER with regards to minimality of encoding of
|
||||
* lengths and integer values. These deviations are still
|
||||
* unambiguous.
|
||||
*/
|
||||
|
||||
unsigned char *buf, *r, *s;
|
||||
size_t zlen, rlen, slen, off;
|
||||
unsigned char tmp[254];
|
||||
|
||||
buf = sig;
|
||||
if (sig_len < 8) {
|
||||
return 0;
|
||||
}
|
||||
if (buf[0] != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
zlen = buf[1];
|
||||
if (zlen > 0x80) {
|
||||
if (zlen != 0x81) {
|
||||
return 0;
|
||||
}
|
||||
zlen = buf[2];
|
||||
if (zlen != sig_len - 3) {
|
||||
return 0;
|
||||
}
|
||||
off = 3;
|
||||
} else {
|
||||
if (zlen != sig_len - 2) {
|
||||
return 0;
|
||||
}
|
||||
off = 2;
|
||||
}
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
rlen = buf[off ++];
|
||||
if (rlen >= 0x80) {
|
||||
return 0;
|
||||
}
|
||||
r = buf + off;
|
||||
off += rlen;
|
||||
if (off + 2 > sig_len) {
|
||||
return 0;
|
||||
}
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
slen = buf[off ++];
|
||||
if (slen >= 0x80 || slen != sig_len - off) {
|
||||
return 0;
|
||||
}
|
||||
s = buf + off;
|
||||
|
||||
while (rlen > 0 && *r == 0) {
|
||||
rlen --;
|
||||
r ++;
|
||||
}
|
||||
while (slen > 0 && *s == 0) {
|
||||
slen --;
|
||||
s ++;
|
||||
}
|
||||
|
||||
zlen = rlen > slen ? rlen : slen;
|
||||
sig_len = zlen << 1;
|
||||
memset(tmp, 0, sig_len);
|
||||
memcpy(tmp + zlen - rlen, r, rlen);
|
||||
memcpy(tmp + sig_len - slen, s, slen);
|
||||
memcpy(sig, tmp, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
47
src/ec/ecdsa_i31_bits.c
Normal file
47
src/ec/ecdsa_i31_bits.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ecdsa_i31_bits2int(uint32_t *x,
|
||||
const void *src, size_t len, uint32_t ebitlen)
|
||||
{
|
||||
uint32_t bitlen, hbitlen;
|
||||
int sc;
|
||||
|
||||
bitlen = ebitlen - (ebitlen >> 5);
|
||||
hbitlen = (uint32_t)len << 3;
|
||||
if (hbitlen > bitlen) {
|
||||
len = (bitlen + 7) >> 3;
|
||||
sc = (int)((hbitlen - bitlen) & 7);
|
||||
} else {
|
||||
sc = 0;
|
||||
}
|
||||
br_i31_zero(x, ebitlen);
|
||||
br_i31_decode(x, src, len);
|
||||
br_i31_rshift(x, sc);
|
||||
x[0] = ebitlen;
|
||||
}
|
||||
45
src/ec/ecdsa_i31_sign_asn1.c
Normal file
45
src/ec/ecdsa_i31_sign_asn1.c
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
unsigned char rsig[(ORDER_LEN << 1) + 12];
|
||||
size_t sig_len;
|
||||
|
||||
sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig);
|
||||
if (sig_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
|
||||
memcpy(sig, rsig, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
176
src/ec/ecdsa_i31_sign_raw.c
Normal file
176
src/ec/ecdsa_i31_sign_raw.c
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
* We also rely on the last byte of the curve order to be distinct
|
||||
* from 0 and 1.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN];
|
||||
uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN];
|
||||
unsigned char tt[ORDER_LEN << 1];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t hash_len, nlen, ulen;
|
||||
uint32_t n0i, ctl;
|
||||
br_hmac_drbg_context drbg;
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (sk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i31_decode(n, cd->order, nlen);
|
||||
n0i = br_i31_ninv31(n[1]);
|
||||
|
||||
/*
|
||||
* Get private key as an i31 integer. This also checks that the
|
||||
* private key is well-defined (not zero, and less than the
|
||||
* curve order).
|
||||
*/
|
||||
if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i31_iszero(x)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get hash length.
|
||||
*/
|
||||
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
|
||||
/*
|
||||
* Truncate and reduce the hash value modulo the curve order.
|
||||
*/
|
||||
br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]);
|
||||
br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* RFC 6979 generation of the "k" value.
|
||||
*
|
||||
* The process uses HMAC_DRBG (with the hash function used to
|
||||
* process the message that is to be signed). The seed is the
|
||||
* concatenation of the encodings of the private key and
|
||||
* the hash value (after truncation and modular reduction).
|
||||
*/
|
||||
br_i31_encode(tt, nlen, x);
|
||||
br_i31_encode(tt + nlen, nlen, m);
|
||||
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
|
||||
for (;;) {
|
||||
br_hmac_drbg_generate(&drbg, tt, nlen);
|
||||
br_ecdsa_i31_bits2int(k, tt, nlen, n[0]);
|
||||
if (br_i31_iszero(k)) {
|
||||
continue;
|
||||
}
|
||||
if (br_i31_sub(k, n, 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute k*G and extract the X coordinate, then reduce it
|
||||
* modulo the curve order. Since we support only curves with
|
||||
* prime order, that reduction is only a matter of computing
|
||||
* a subtraction.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, cd->generator, ulen);
|
||||
br_i31_encode(tt, nlen, k);
|
||||
if (!impl->mul(eU, ulen, tt, nlen, sk->curve)) {
|
||||
/*
|
||||
* Point multiplication may fail here only if the
|
||||
* EC implementation does not support the curve, or the
|
||||
* private key is incorrect (x is a multiple of the curve
|
||||
* order).
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
br_i31_zero(r, n[0]);
|
||||
br_i31_decode(r, &eU[1], ulen >> 1);
|
||||
r[0] = n[0];
|
||||
br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Compute 1/k in double-Montgomery representation. We do so by
|
||||
* first converting _from_ Montgomery representation (twice),
|
||||
* then using a modular exponentiation.
|
||||
*/
|
||||
br_i31_from_monty(k, n, n0i);
|
||||
br_i31_from_monty(k, n, n0i);
|
||||
memcpy(tt, cd->order, nlen);
|
||||
tt[nlen - 1] -= 2;
|
||||
br_i31_modpow(k, tt, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s = (m+xr)/k (mod n).
|
||||
* The k[] array contains R^2/k (double-Montgomery representation);
|
||||
* we thus can use direct Montgomery multiplications and conversions
|
||||
* from Montgomery, avoiding any call to br_i31_to_monty() (which
|
||||
* is slower).
|
||||
*/
|
||||
br_i31_from_monty(m, n, n0i);
|
||||
br_i31_montymul(t1, x, r, n, n0i);
|
||||
ctl = br_i31_add(t1, m, 1);
|
||||
ctl |= br_i31_sub(t1, n, 0) ^ 1;
|
||||
br_i31_sub(t1, n, ctl);
|
||||
br_i31_montymul(s, t1, k, n, n0i);
|
||||
|
||||
/*
|
||||
* Encode r and s in the signature.
|
||||
*/
|
||||
br_i31_encode(sig, nlen, r);
|
||||
br_i31_encode((unsigned char *)sig + nlen, nlen, s);
|
||||
return nlen << 1;
|
||||
}
|
||||
44
src/ec/ecdsa_i31_vrfy_asn1.c
Normal file
44
src/ec/ecdsa_i31_vrfy_asn1.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
unsigned char rsig[(FIELD_LEN << 1) + 12];
|
||||
|
||||
if (sig_len > sizeof rsig) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(rsig, sig, sig_len);
|
||||
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
|
||||
return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
|
||||
}
|
||||
158
src/ec/ecdsa_i31_vrfy_raw.c
Normal file
158
src/ec/ecdsa_i31_vrfy_raw.c
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN];
|
||||
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t nlen, rlen, ulen;
|
||||
uint32_t n0i, res;
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (pk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signature length must be even.
|
||||
*/
|
||||
if (sig_len & 1) {
|
||||
return 0;
|
||||
}
|
||||
rlen = sig_len >> 1;
|
||||
|
||||
/*
|
||||
* Public key point must have the proper size for this curve.
|
||||
*/
|
||||
if (pk->qlen != cd->generator_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus; then decode the r and s values. They must be
|
||||
* lower than the modulus, and s must not be null.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i31_decode(n, cd->order, nlen);
|
||||
n0i = br_i31_ninv31(n[1]);
|
||||
if (!br_i31_decode_mod(r, sig, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i31_iszero(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert s. We do that with a modular exponentiation; we use
|
||||
* the fact that for all the curves we support, the least
|
||||
* significant byte is not 0 or 1, so we can subtract 2 without
|
||||
* any carry to process.
|
||||
* We also want 1/s in Montgomery representation, which can be
|
||||
* done by converting _from_ Montgomery representation before
|
||||
* the inversion (because (1/s)*R = 1/(s/R)).
|
||||
*/
|
||||
br_i31_from_monty(s, n, n0i);
|
||||
memcpy(tx, cd->order, nlen);
|
||||
tx[nlen - 1] -= 2;
|
||||
br_i31_modpow(s, tx, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Truncate the hash to the modulus length (in bits) and reduce
|
||||
* it modulo the curve order. The modular reduction can be done
|
||||
* with a subtraction since the truncation already reduced the
|
||||
* value to the modulus bit length.
|
||||
*/
|
||||
br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]);
|
||||
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Multiply the (truncated, reduced) hash value with 1/s, result in
|
||||
* t2, encoded in ty.
|
||||
*/
|
||||
br_i31_montymul(t2, t1, s, n, n0i);
|
||||
br_i31_encode(ty, nlen, t2);
|
||||
|
||||
/*
|
||||
* Multiply r with 1/s, result in t1, encoded in tx.
|
||||
*/
|
||||
br_i31_montymul(t1, r, s, n, n0i);
|
||||
br_i31_encode(tx, nlen, t1);
|
||||
|
||||
/*
|
||||
* Compute the point x*Q + y*G.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, pk->q, ulen);
|
||||
res = impl->muladd(eU, cd->generator, ulen,
|
||||
tx, nlen, ty, nlen, cd->curve);
|
||||
|
||||
/*
|
||||
* Get the X coordinate, reduce modulo the curve order, and
|
||||
* compare with the 'r' value.
|
||||
*
|
||||
* The modular reduction can be done with subtractions because
|
||||
* we work with curves of prime order, so the curve order is
|
||||
* close to the field order (Hasse's theorem).
|
||||
*/
|
||||
br_i31_zero(t1, n[0]);
|
||||
br_i31_decode(t1, &eU[1], ulen >> 1);
|
||||
t1[0] = n[0];
|
||||
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
|
||||
res &= ~br_i31_sub(t1, r, 1);
|
||||
res &= br_i31_iszero(t1);
|
||||
return res;
|
||||
}
|
||||
94
src/ec/ecdsa_rta.c
Normal file
94
src/ec/ecdsa_rta.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static size_t
|
||||
asn1_int_length(const unsigned char *x, size_t xlen)
|
||||
{
|
||||
while (xlen > 0 && *x == 0) {
|
||||
x ++;
|
||||
xlen --;
|
||||
}
|
||||
if (xlen == 0 || *x >= 0x80) {
|
||||
xlen ++;
|
||||
}
|
||||
return xlen;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_raw_to_asn1(void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* Internal buffer is large enough to accommodate a signature
|
||||
* such that r and s fit on 125 bytes each (signed encoding),
|
||||
* meaning a curve order of up to 1000 bits. This is the limit
|
||||
* that ensures "simple" length encodings.
|
||||
*/
|
||||
unsigned char *buf;
|
||||
size_t hlen, rlen, slen, zlen, off;
|
||||
unsigned char tmp[257];
|
||||
|
||||
buf = sig;
|
||||
if ((sig_len & 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
hlen = sig_len >> 1;
|
||||
rlen = asn1_int_length(buf, hlen);
|
||||
slen = asn1_int_length(buf + hlen, hlen);
|
||||
if (rlen > 125 || slen > 125) {
|
||||
return 0;
|
||||
}
|
||||
tmp[0] = 0x30;
|
||||
zlen = rlen + slen + 4;
|
||||
if (zlen >= 0x80) {
|
||||
tmp[1] = 0x81;
|
||||
tmp[2] = zlen;
|
||||
off = 3;
|
||||
} else {
|
||||
tmp[1] = zlen;
|
||||
off = 2;
|
||||
}
|
||||
tmp[off ++] = 0x02;
|
||||
tmp[off ++] = rlen;
|
||||
if (rlen > hlen) {
|
||||
tmp[off] = 0x00;
|
||||
memcpy(tmp + off + 1, buf, hlen);
|
||||
} else {
|
||||
memcpy(tmp + off, buf + hlen - rlen, rlen);
|
||||
}
|
||||
off += rlen;
|
||||
tmp[off ++] = 0x02;
|
||||
tmp[off ++] = slen;
|
||||
if (slen > hlen) {
|
||||
tmp[off] = 0x00;
|
||||
memcpy(tmp + off + 1, buf + hlen, hlen);
|
||||
} else {
|
||||
memcpy(tmp + off, buf + sig_len - slen, slen);
|
||||
}
|
||||
off += slen;
|
||||
memcpy(sig, tmp, off);
|
||||
return off;
|
||||
}
|
||||
78
src/hash/dig_oid.c
Normal file
78
src/hash/dig_oid.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char md5_OID[] = {
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05
|
||||
};
|
||||
|
||||
static const unsigned char sha1_OID[] = {
|
||||
0x2B, 0x0E, 0x03, 0x02, 0x1A
|
||||
};
|
||||
|
||||
static const unsigned char sha224_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
|
||||
};
|
||||
|
||||
static const unsigned char sha256_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||
};
|
||||
|
||||
static const unsigned char sha384_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||
};
|
||||
|
||||
static const unsigned char sha512_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const unsigned char *
|
||||
br_digest_OID(int digest_id, size_t *len)
|
||||
{
|
||||
switch (digest_id) {
|
||||
case br_md5_ID:
|
||||
*len = sizeof md5_OID;
|
||||
return md5_OID;
|
||||
case br_sha1_ID:
|
||||
*len = sizeof sha1_OID;
|
||||
return sha1_OID;
|
||||
case br_sha224_ID:
|
||||
*len = sizeof sha224_OID;
|
||||
return sha224_OID;
|
||||
case br_sha256_ID:
|
||||
*len = sizeof sha256_OID;
|
||||
return sha256_OID;
|
||||
case br_sha384_ID:
|
||||
*len = sizeof sha384_OID;
|
||||
return sha384_OID;
|
||||
case br_sha512_ID:
|
||||
*len = sizeof sha512_OID;
|
||||
return sha512_OID;
|
||||
default:
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
50
src/hash/dig_size.c
Normal file
50
src/hash/dig_size.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
size_t
|
||||
br_digest_size_by_ID(int digest_id)
|
||||
{
|
||||
switch (digest_id) {
|
||||
case br_md5sha1_ID:
|
||||
return br_md5_SIZE + br_sha1_SIZE;
|
||||
case br_md5_ID:
|
||||
return br_md5_SIZE;
|
||||
case br_sha1_ID:
|
||||
return br_sha1_SIZE;
|
||||
case br_sha224_ID:
|
||||
return br_sha224_SIZE;
|
||||
case br_sha256_ID:
|
||||
return br_sha256_SIZE;
|
||||
case br_sha384_ID:
|
||||
return br_sha384_SIZE;
|
||||
case br_sha512_ID:
|
||||
return br_sha512_SIZE;
|
||||
default:
|
||||
/* abort(); */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
311
src/hash/ghash_ctmul.c
Normal file
311
src/hash/ghash_ctmul.c
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* We compute "carryless multiplications" through normal integer
|
||||
* multiplications, masking out enough bits to create "holes" in which
|
||||
* carries may expand without altering our bits; we really use 8 data
|
||||
* bits per 32-bit word, space every fourth bit. Accumulated carries
|
||||
* may not exceed 8 in total, which fits in 4 bits.
|
||||
*
|
||||
* It would be possible to use a 3-bit spacing, allowing two operands,
|
||||
* one with 7 non-zero data bits, the other one with 10 or 11 non-zero
|
||||
* data bits; this asymmetric splitting makes the overall code more
|
||||
* complex with thresholds and exceptions, and does not appear to be
|
||||
* worth the effort.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We cannot really autodetect whether multiplications are "slow" or
|
||||
* not. A typical example is the ARM Cortex M0+, which exists in two
|
||||
* versions: one with a 1-cycle multiplication opcode, the other with
|
||||
* a 32-cycle multiplication opcodes. They both use exactly the same
|
||||
* architecture and ABI, and cannot be distinguished from each other
|
||||
* at compile-time.
|
||||
*
|
||||
* Since most modern CPU (even embedded CPU) still have fast
|
||||
* multiplications, we use the "fast mul" code by default.
|
||||
*/
|
||||
|
||||
#if BR_SLOW_MUL
|
||||
|
||||
/*
|
||||
* This implementation uses Karatsuba-like reduction to make fewer
|
||||
* integer multiplications (9 instead of 16), at the expense of extra
|
||||
* logical operations (XOR, shifts...). On modern x86 CPU that offer
|
||||
* fast, pipelined multiplications, this code is about twice slower than
|
||||
* the simpler code with 16 multiplications. This tendency may be
|
||||
* reversed on low-end platforms with expensive multiplications.
|
||||
*/
|
||||
|
||||
#define MUL32(h, l, x, y) do { \
|
||||
uint64_t mul32tmp = MUL(x, y); \
|
||||
(h) = (uint32_t)(mul32tmp >> 32); \
|
||||
(l) = (uint32_t)mul32tmp; \
|
||||
} while (0)
|
||||
|
||||
static inline void
|
||||
bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8;
|
||||
uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
|
||||
/*
|
||||
* (x0+W*x1)*(y0+W*y1) -> a0:b0
|
||||
* (x2+W*x3)*(y2+W*y3) -> a3:b3
|
||||
* ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6
|
||||
*/
|
||||
a0 = x0;
|
||||
b0 = y0;
|
||||
a1 = x1 >> 1;
|
||||
b1 = y1 >> 1;
|
||||
a2 = a0 ^ a1;
|
||||
b2 = b0 ^ b1;
|
||||
a3 = x2 >> 2;
|
||||
b3 = y2 >> 2;
|
||||
a4 = x3 >> 3;
|
||||
b4 = y3 >> 3;
|
||||
a5 = a3 ^ a4;
|
||||
b5 = b3 ^ b4;
|
||||
a6 = a0 ^ a3;
|
||||
b6 = b0 ^ b3;
|
||||
a7 = a1 ^ a4;
|
||||
b7 = b1 ^ b4;
|
||||
a8 = a6 ^ a7;
|
||||
b8 = b6 ^ b7;
|
||||
|
||||
MUL32(b0, a0, b0, a0);
|
||||
MUL32(b1, a1, b1, a1);
|
||||
MUL32(b2, a2, b2, a2);
|
||||
MUL32(b3, a3, b3, a3);
|
||||
MUL32(b4, a4, b4, a4);
|
||||
MUL32(b5, a5, b5, a5);
|
||||
MUL32(b6, a6, b6, a6);
|
||||
MUL32(b7, a7, b7, a7);
|
||||
MUL32(b8, a8, b8, a8);
|
||||
|
||||
a0 &= (uint32_t)0x11111111;
|
||||
a1 &= (uint32_t)0x11111111;
|
||||
a2 &= (uint32_t)0x11111111;
|
||||
a3 &= (uint32_t)0x11111111;
|
||||
a4 &= (uint32_t)0x11111111;
|
||||
a5 &= (uint32_t)0x11111111;
|
||||
a6 &= (uint32_t)0x11111111;
|
||||
a7 &= (uint32_t)0x11111111;
|
||||
a8 &= (uint32_t)0x11111111;
|
||||
b0 &= (uint32_t)0x11111111;
|
||||
b1 &= (uint32_t)0x11111111;
|
||||
b2 &= (uint32_t)0x11111111;
|
||||
b3 &= (uint32_t)0x11111111;
|
||||
b4 &= (uint32_t)0x11111111;
|
||||
b5 &= (uint32_t)0x11111111;
|
||||
b6 &= (uint32_t)0x11111111;
|
||||
b7 &= (uint32_t)0x11111111;
|
||||
b8 &= (uint32_t)0x11111111;
|
||||
|
||||
a2 ^= a0 ^ a1;
|
||||
b2 ^= b0 ^ b1;
|
||||
a0 ^= (a2 << 1) ^ (a1 << 2);
|
||||
b0 ^= (b2 << 1) ^ (b1 << 2);
|
||||
a5 ^= a3 ^ a4;
|
||||
b5 ^= b3 ^ b4;
|
||||
a3 ^= (a5 << 1) ^ (a4 << 2);
|
||||
b3 ^= (b5 << 1) ^ (b4 << 2);
|
||||
a8 ^= a6 ^ a7;
|
||||
b8 ^= b6 ^ b7;
|
||||
a6 ^= (a8 << 1) ^ (a7 << 2);
|
||||
b6 ^= (b8 << 1) ^ (b7 << 2);
|
||||
a6 ^= a0 ^ a3;
|
||||
b6 ^= b0 ^ b3;
|
||||
*lo = a0 ^ (a6 << 2) ^ (a3 << 4);
|
||||
*hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Simple multiplication in GF(2)[X], using 16 integer multiplications.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint64_t z0, z1, z2, z3;
|
||||
uint64_t z;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1);
|
||||
z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2);
|
||||
z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3);
|
||||
z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0);
|
||||
z0 &= (uint64_t)0x1111111111111111;
|
||||
z1 &= (uint64_t)0x2222222222222222;
|
||||
z2 &= (uint64_t)0x4444444444444444;
|
||||
z3 &= (uint64_t)0x8888888888888888;
|
||||
z = z0 | z1 | z2 | z3;
|
||||
*lo = (uint32_t)z;
|
||||
*hi = (uint32_t)(z >> 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_ghash_ctmul(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint32_t yw[4];
|
||||
uint32_t hw[4];
|
||||
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
yw[3] = br_dec32be(yb);
|
||||
yw[2] = br_dec32be(yb + 4);
|
||||
yw[1] = br_dec32be(yb + 8);
|
||||
yw[0] = br_dec32be(yb + 12);
|
||||
hw[3] = br_dec32be(hb);
|
||||
hw[2] = br_dec32be(hb + 4);
|
||||
hw[1] = br_dec32be(hb + 8);
|
||||
hw[0] = br_dec32be(hb + 12);
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
uint32_t a[9], b[9], zw[8];
|
||||
uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3;
|
||||
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
yw[3] ^= br_dec32be(src);
|
||||
yw[2] ^= br_dec32be(src + 4);
|
||||
yw[1] ^= br_dec32be(src + 8);
|
||||
yw[0] ^= br_dec32be(src + 12);
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0..2
|
||||
* y[2,3]*h[2,3] -> 3..5
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8
|
||||
*/
|
||||
a[0] = yw[0];
|
||||
b[0] = hw[0];
|
||||
a[1] = yw[1];
|
||||
b[1] = hw[1];
|
||||
a[2] = a[0] ^ a[1];
|
||||
b[2] = b[0] ^ b[1];
|
||||
|
||||
a[3] = yw[2];
|
||||
b[3] = hw[2];
|
||||
a[4] = yw[3];
|
||||
b[4] = hw[3];
|
||||
a[5] = a[3] ^ a[4];
|
||||
b[5] = b[3] ^ b[4];
|
||||
|
||||
a[6] = a[0] ^ a[3];
|
||||
b[6] = b[0] ^ b[3];
|
||||
a[7] = a[1] ^ a[4];
|
||||
b[7] = b[1] ^ b[4];
|
||||
a[8] = a[6] ^ a[7];
|
||||
b[8] = b[6] ^ b[7];
|
||||
|
||||
for (i = 0; i < 9; i ++) {
|
||||
bmul(&b[i], &a[i], b[i], a[i]);
|
||||
}
|
||||
|
||||
c0 = a[0];
|
||||
c1 = b[0] ^ a[2] ^ a[0] ^ a[1];
|
||||
c2 = a[1] ^ b[2] ^ b[0] ^ b[1];
|
||||
c3 = b[1];
|
||||
d0 = a[3];
|
||||
d1 = b[3] ^ a[5] ^ a[3] ^ a[4];
|
||||
d2 = a[4] ^ b[5] ^ b[3] ^ b[4];
|
||||
d3 = b[4];
|
||||
e0 = a[6];
|
||||
e1 = b[6] ^ a[8] ^ a[6] ^ a[7];
|
||||
e2 = a[7] ^ b[8] ^ b[6] ^ b[7];
|
||||
e3 = b[7];
|
||||
|
||||
e0 ^= c0 ^ d0;
|
||||
e1 ^= c1 ^ d1;
|
||||
e2 ^= c2 ^ d2;
|
||||
e3 ^= c3 ^ d3;
|
||||
c2 ^= e0;
|
||||
c3 ^= e1;
|
||||
d0 ^= e2;
|
||||
d1 ^= e3;
|
||||
|
||||
zw[0] = c0 << 1;
|
||||
zw[1] = (c1 << 1) | (c0 >> 31);
|
||||
zw[2] = (c2 << 1) | (c1 >> 31);
|
||||
zw[3] = (c3 << 1) | (c2 >> 31);
|
||||
zw[4] = (d0 << 1) | (c3 >> 31);
|
||||
zw[5] = (d1 << 1) | (d0 >> 31);
|
||||
zw[6] = (d2 << 1) | (d1 >> 31);
|
||||
zw[7] = (d3 << 1) | (d2 >> 31);
|
||||
|
||||
for (i = 0; i < 4; i ++) {
|
||||
uint32_t lw;
|
||||
|
||||
lw = zw[i];
|
||||
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
|
||||
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
|
||||
}
|
||||
memcpy(yw, zw + 4, sizeof yw);
|
||||
}
|
||||
br_enc32be(yb, yw[3]);
|
||||
br_enc32be(yb + 4, yw[2]);
|
||||
br_enc32be(yb + 8, yw[1]);
|
||||
br_enc32be(yb + 12, yw[0]);
|
||||
}
|
||||
244
src/hash/ghash_ctmul32.c
Normal file
244
src/hash/ghash_ctmul32.c
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This implementation uses 32-bit multiplications, and only the low
|
||||
* 32 bits for each multiplication result. This is meant primarily for
|
||||
* the ARM Cortex M0 and M0+, whose multiplication opcode does not yield
|
||||
* the upper 32 bits; but it might also be useful on architectures where
|
||||
* access to the upper 32 bits requires use of specific registers that
|
||||
* create contention (e.g. on i386, "mul" necessarily outputs the result
|
||||
* in edx:eax, while "imul" can use any registers but is limited to the
|
||||
* low 32 bits).
|
||||
*
|
||||
* The implementation trick that is used here is bit-reversing (bit 0
|
||||
* is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X],
|
||||
* for all values x and y, we have:
|
||||
* rev32(x) * rev32(y) = rev64(x * y)
|
||||
* In other words, if we bit-reverse (over 32 bits) the operands, then we
|
||||
* bit-reverse (over 64 bits) the result.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Multiplication in GF(2)[X], truncated to its low 32 bits.
|
||||
*/
|
||||
static inline uint32_t
|
||||
bmul32(uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint32_t z0, z1, z2, z3;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
|
||||
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
|
||||
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
|
||||
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
|
||||
z0 &= (uint32_t)0x11111111;
|
||||
z1 &= (uint32_t)0x22222222;
|
||||
z2 &= (uint32_t)0x44444444;
|
||||
z3 &= (uint32_t)0x88888888;
|
||||
return z0 | z1 | z2 | z3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit-reverse a 32-bit word.
|
||||
*/
|
||||
static uint32_t
|
||||
rev32(uint32_t x)
|
||||
{
|
||||
#define RMS(m, s) do { \
|
||||
x = ((x & (uint32_t)(m)) << (s)) \
|
||||
| ((x >> (s)) & (uint32_t)(m)); \
|
||||
} while (0)
|
||||
|
||||
RMS(0x55555555, 1);
|
||||
RMS(0x33333333, 2);
|
||||
RMS(0x0F0F0F0F, 4);
|
||||
RMS(0x00FF00FF, 8);
|
||||
return (x << 16) | (x >> 16);
|
||||
|
||||
#undef RMS
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint32_t yw[4];
|
||||
uint32_t hw[4], hwr[4];
|
||||
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
yw[3] = br_dec32be(yb);
|
||||
yw[2] = br_dec32be(yb + 4);
|
||||
yw[1] = br_dec32be(yb + 8);
|
||||
yw[0] = br_dec32be(yb + 12);
|
||||
hw[3] = br_dec32be(hb);
|
||||
hw[2] = br_dec32be(hb + 4);
|
||||
hw[1] = br_dec32be(hb + 8);
|
||||
hw[0] = br_dec32be(hb + 12);
|
||||
hwr[3] = rev32(hw[3]);
|
||||
hwr[2] = rev32(hw[2]);
|
||||
hwr[1] = rev32(hw[1]);
|
||||
hwr[0] = rev32(hw[0]);
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
uint32_t a[18], b[18], c[18];
|
||||
uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
|
||||
uint32_t zw[8];
|
||||
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
yw[3] ^= br_dec32be(src);
|
||||
yw[2] ^= br_dec32be(src + 4);
|
||||
yw[1] ^= br_dec32be(src + 8);
|
||||
yw[0] ^= br_dec32be(src + 12);
|
||||
|
||||
/*
|
||||
* We are using Karatsuba: the 128x128 multiplication is
|
||||
* reduced to three 64x64 multiplications, hence nine
|
||||
* 32x32 multiplications. With the bit-reversal trick,
|
||||
* we have to perform 18 32x32 multiplications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0,1,4
|
||||
* y[2,3]*h[2,3] -> 2,3,5
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8
|
||||
*/
|
||||
|
||||
a[0] = yw[0];
|
||||
a[1] = yw[1];
|
||||
a[2] = yw[2];
|
||||
a[3] = yw[3];
|
||||
a[4] = a[0] ^ a[1];
|
||||
a[5] = a[2] ^ a[3];
|
||||
a[6] = a[0] ^ a[2];
|
||||
a[7] = a[1] ^ a[3];
|
||||
a[8] = a[6] ^ a[7];
|
||||
|
||||
a[ 9] = rev32(yw[0]);
|
||||
a[10] = rev32(yw[1]);
|
||||
a[11] = rev32(yw[2]);
|
||||
a[12] = rev32(yw[3]);
|
||||
a[13] = a[ 9] ^ a[10];
|
||||
a[14] = a[11] ^ a[12];
|
||||
a[15] = a[ 9] ^ a[11];
|
||||
a[16] = a[10] ^ a[12];
|
||||
a[17] = a[15] ^ a[16];
|
||||
|
||||
b[0] = hw[0];
|
||||
b[1] = hw[1];
|
||||
b[2] = hw[2];
|
||||
b[3] = hw[3];
|
||||
b[4] = b[0] ^ b[1];
|
||||
b[5] = b[2] ^ b[3];
|
||||
b[6] = b[0] ^ b[2];
|
||||
b[7] = b[1] ^ b[3];
|
||||
b[8] = b[6] ^ b[7];
|
||||
|
||||
b[ 9] = hwr[0];
|
||||
b[10] = hwr[1];
|
||||
b[11] = hwr[2];
|
||||
b[12] = hwr[3];
|
||||
b[13] = b[ 9] ^ b[10];
|
||||
b[14] = b[11] ^ b[12];
|
||||
b[15] = b[ 9] ^ b[11];
|
||||
b[16] = b[10] ^ b[12];
|
||||
b[17] = b[15] ^ b[16];
|
||||
|
||||
for (i = 0; i < 18; i ++) {
|
||||
c[i] = bmul32(a[i], b[i]);
|
||||
}
|
||||
|
||||
c[4] ^= c[0] ^ c[1];
|
||||
c[5] ^= c[2] ^ c[3];
|
||||
c[8] ^= c[6] ^ c[7];
|
||||
|
||||
c[13] ^= c[ 9] ^ c[10];
|
||||
c[14] ^= c[11] ^ c[12];
|
||||
c[17] ^= c[15] ^ c[16];
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0,9^4,1^13,10
|
||||
* y[2,3]*h[2,3] -> 2,11^5,3^14,12
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16
|
||||
*/
|
||||
d0 = c[0];
|
||||
d1 = c[4] ^ (rev32(c[9]) >> 1);
|
||||
d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1);
|
||||
d3 = c[4] ^ c[5] ^ c[8]
|
||||
^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1);
|
||||
d4 = c[2] ^ c[1] ^ c[3] ^ c[7]
|
||||
^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1);
|
||||
d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1);
|
||||
d6 = c[3] ^ (rev32(c[14]) >> 1);
|
||||
d7 = rev32(c[12]) >> 1;
|
||||
|
||||
zw[0] = d0 << 1;
|
||||
zw[1] = (d1 << 1) | (d0 >> 31);
|
||||
zw[2] = (d2 << 1) | (d1 >> 31);
|
||||
zw[3] = (d3 << 1) | (d2 >> 31);
|
||||
zw[4] = (d4 << 1) | (d3 >> 31);
|
||||
zw[5] = (d5 << 1) | (d4 >> 31);
|
||||
zw[6] = (d6 << 1) | (d5 >> 31);
|
||||
zw[7] = (d7 << 1) | (d6 >> 31);
|
||||
|
||||
for (i = 0; i < 4; i ++) {
|
||||
uint32_t lw;
|
||||
|
||||
lw = zw[i];
|
||||
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
|
||||
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
|
||||
}
|
||||
memcpy(yw, zw + 4, sizeof yw);
|
||||
}
|
||||
br_enc32be(yb, yw[3]);
|
||||
br_enc32be(yb + 4, yw[2]);
|
||||
br_enc32be(yb + 8, yw[1]);
|
||||
br_enc32be(yb + 12, yw[0]);
|
||||
}
|
||||
154
src/hash/ghash_ctmul64.c
Normal file
154
src/hash/ghash_ctmul64.c
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This is the 64-bit variant of ghash_ctmul32(), with 64-bit operands
|
||||
* and bit reversal of 64-bit words.
|
||||
*/
|
||||
|
||||
static inline uint64_t
|
||||
bmul64(uint64_t x, uint64_t y)
|
||||
{
|
||||
uint64_t x0, x1, x2, x3;
|
||||
uint64_t y0, y1, y2, y3;
|
||||
uint64_t z0, z1, z2, z3;
|
||||
|
||||
x0 = x & (uint64_t)0x1111111111111111;
|
||||
x1 = x & (uint64_t)0x2222222222222222;
|
||||
x2 = x & (uint64_t)0x4444444444444444;
|
||||
x3 = x & (uint64_t)0x8888888888888888;
|
||||
y0 = y & (uint64_t)0x1111111111111111;
|
||||
y1 = y & (uint64_t)0x2222222222222222;
|
||||
y2 = y & (uint64_t)0x4444444444444444;
|
||||
y3 = y & (uint64_t)0x8888888888888888;
|
||||
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
|
||||
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
|
||||
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
|
||||
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
|
||||
z0 &= (uint64_t)0x1111111111111111;
|
||||
z1 &= (uint64_t)0x2222222222222222;
|
||||
z2 &= (uint64_t)0x4444444444444444;
|
||||
z3 &= (uint64_t)0x8888888888888888;
|
||||
return z0 | z1 | z2 | z3;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
rev64(uint64_t x)
|
||||
{
|
||||
#define RMS(m, s) do { \
|
||||
x = ((x & (uint64_t)(m)) << (s)) \
|
||||
| ((x >> (s)) & (uint64_t)(m)); \
|
||||
} while (0)
|
||||
|
||||
RMS(0x5555555555555555, 1);
|
||||
RMS(0x3333333333333333, 2);
|
||||
RMS(0x0F0F0F0F0F0F0F0F, 4);
|
||||
RMS(0x00FF00FF00FF00FF, 8);
|
||||
RMS(0x0000FFFF0000FFFF, 16);
|
||||
return (x << 32) | (x >> 32);
|
||||
|
||||
#undef RMS
|
||||
}
|
||||
|
||||
/* see bearssl_ghash.h */
|
||||
void
|
||||
br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint64_t y0, y1;
|
||||
uint64_t h0, h1, h2, h0r, h1r, h2r;
|
||||
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
y1 = br_dec64be(yb);
|
||||
y0 = br_dec64be(yb + 8);
|
||||
h1 = br_dec64be(hb);
|
||||
h0 = br_dec64be(hb + 8);
|
||||
h0r = rev64(h0);
|
||||
h1r = rev64(h1);
|
||||
h2 = h0 ^ h1;
|
||||
h2r = h0r ^ h1r;
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
uint64_t y0r, y1r, y2, y2r;
|
||||
uint64_t z0, z1, z2, z0h, z1h, z2h;
|
||||
uint64_t v0, v1, v2, v3;
|
||||
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
y1 ^= br_dec64be(src);
|
||||
y0 ^= br_dec64be(src + 8);
|
||||
|
||||
y0r = rev64(y0);
|
||||
y1r = rev64(y1);
|
||||
y2 = y0 ^ y1;
|
||||
y2r = y0r ^ y1r;
|
||||
|
||||
z0 = bmul64(y0, h0);
|
||||
z1 = bmul64(y1, h1);
|
||||
z2 = bmul64(y2, h2);
|
||||
z0h = bmul64(y0r, h0r);
|
||||
z1h = bmul64(y1r, h1r);
|
||||
z2h = bmul64(y2r, h2r);
|
||||
z2 ^= z0 ^ z1;
|
||||
z2h ^= z0h ^ z1h;
|
||||
z0h = rev64(z0h) >> 1;
|
||||
z1h = rev64(z1h) >> 1;
|
||||
z2h = rev64(z2h) >> 1;
|
||||
|
||||
v0 = z0;
|
||||
v1 = z0h ^ z2;
|
||||
v2 = z1 ^ z2h;
|
||||
v3 = z1h;
|
||||
|
||||
v3 = (v3 << 1) | (v2 >> 63);
|
||||
v2 = (v2 << 1) | (v1 >> 63);
|
||||
v1 = (v1 << 1) | (v0 >> 63);
|
||||
v0 = (v0 << 1);
|
||||
|
||||
v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
|
||||
v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
|
||||
v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
|
||||
v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
|
||||
|
||||
y0 = v2;
|
||||
y1 = v3;
|
||||
}
|
||||
|
||||
br_enc64be(yb, y1);
|
||||
br_enc64be(yb + 8, y0);
|
||||
}
|
||||
208
src/hash/md5.c
Normal file
208
src/hash/md5.c
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
|
||||
#define G(B, C, D) ((((C) ^ (B)) & (D)) ^ (C))
|
||||
#define H(B, C, D) ((B) ^ (C) ^ (D))
|
||||
#define I(B, C, D) ((C) ^ ((B) | ~(D)))
|
||||
|
||||
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_md5_IV[4] = {
|
||||
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476
|
||||
};
|
||||
|
||||
static const uint32_t K[64] = {
|
||||
0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
|
||||
0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
|
||||
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
|
||||
0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
|
||||
|
||||
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
|
||||
0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
|
||||
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
|
||||
0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
|
||||
|
||||
0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
|
||||
0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
|
||||
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
|
||||
0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
|
||||
|
||||
0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
|
||||
0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
|
||||
0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
|
||||
0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
|
||||
};
|
||||
|
||||
static const unsigned char MP[48] = {
|
||||
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
|
||||
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
|
||||
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_md5_round(const unsigned char *buf, uint32_t *val)
|
||||
{
|
||||
uint32_t m[16];
|
||||
uint32_t a, b, c, d;
|
||||
int i;
|
||||
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
/* obsolete
|
||||
for (i = 0; i < 16; i ++) {
|
||||
m[i] = br_dec32le(buf + (i << 2));
|
||||
}
|
||||
*/
|
||||
br_range_dec32le(m, 16, buf);
|
||||
|
||||
for (i = 0; i < 16; i += 4) {
|
||||
a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0], 7);
|
||||
d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12);
|
||||
c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17);
|
||||
b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22);
|
||||
}
|
||||
for (i = 16; i < 32; i += 4) {
|
||||
a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0], 5);
|
||||
d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1], 9);
|
||||
c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14);
|
||||
b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20);
|
||||
}
|
||||
for (i = 32; i < 48; i += 4) {
|
||||
a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0], 4);
|
||||
d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11);
|
||||
c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16);
|
||||
b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23);
|
||||
}
|
||||
for (i = 48; i < 64; i += 4) {
|
||||
a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0], 6);
|
||||
d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10);
|
||||
c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15);
|
||||
b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21);
|
||||
}
|
||||
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_init(br_md5_context *cc)
|
||||
{
|
||||
cc->vtable = &br_md5_vtable;
|
||||
memcpy(cc->val, br_md5_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_update(br_md5_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
cc->count += (uint64_t)clen;
|
||||
if (ptr == 64) {
|
||||
br_md5_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_out(const br_md5_context *cc, void *dst)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val[4];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_md5_round(buf, val);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
br_enc64le(buf + 56, cc->count << 3);
|
||||
br_md5_round(buf, val);
|
||||
br_range_enc32le(dst, val, 4);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_md5_state(const br_md5_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc32le(dst, cc->val, 4);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_set_state(br_md5_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec32le(cc->val, 4, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_md5_vtable = {
|
||||
sizeof(br_md5_context),
|
||||
BR_HASHDESC_ID(br_md5_ID)
|
||||
| BR_HASHDESC_OUT(16)
|
||||
| BR_HASHDESC_STATE(16)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING,
|
||||
(void (*)(const br_hash_class **))&br_md5_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))&br_md5_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_md5_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_md5_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_md5_set_state
|
||||
};
|
||||
141
src/hash/md5sha1.c
Normal file
141
src/hash/md5sha1.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_init(br_md5sha1_context *cc)
|
||||
{
|
||||
cc->vtable = &br_md5sha1_vtable;
|
||||
memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5);
|
||||
memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
cc->count += (uint64_t)clen;
|
||||
if (ptr == 64) {
|
||||
br_md5_round(cc->buf, cc->val_md5);
|
||||
br_sha1_round(cc->buf, cc->val_sha1);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_out(const br_md5sha1_context *cc, void *dst)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val_md5[4];
|
||||
uint32_t val_sha1[5];
|
||||
size_t ptr;
|
||||
unsigned char *out;
|
||||
uint64_t count;
|
||||
|
||||
count = cc->count;
|
||||
ptr = (size_t)count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val_md5, cc->val_md5, sizeof val_md5);
|
||||
memcpy(val_sha1, cc->val_sha1, sizeof val_sha1);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_md5_round(buf, val_md5);
|
||||
br_sha1_round(buf, val_sha1);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
count <<= 3;
|
||||
br_enc64le(buf + 56, count);
|
||||
br_md5_round(buf, val_md5);
|
||||
br_enc64be(buf + 56, count);
|
||||
br_sha1_round(buf, val_sha1);
|
||||
out = dst;
|
||||
br_range_enc32le(out, val_md5, 4);
|
||||
br_range_enc32be(out + 16, val_sha1, 5);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_md5sha1_state(const br_md5sha1_context *cc, void *dst)
|
||||
{
|
||||
unsigned char *out;
|
||||
|
||||
out = dst;
|
||||
br_range_enc32le(out, cc->val_md5, 4);
|
||||
br_range_enc32be(out + 16, cc->val_sha1, 5);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_set_state(br_md5sha1_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = stb;
|
||||
br_range_dec32le(cc->val_md5, 4, buf);
|
||||
br_range_dec32be(cc->val_sha1, 5, buf + 16);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_md5sha1_vtable = {
|
||||
sizeof(br_md5sha1_context),
|
||||
BR_HASHDESC_ID(br_md5sha1_ID)
|
||||
| BR_HASHDESC_OUT(36)
|
||||
| BR_HASHDESC_STATE(36)
|
||||
| BR_HASHDESC_LBLEN(6),
|
||||
(void (*)(const br_hash_class **))&br_md5sha1_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))
|
||||
&br_md5sha1_update,
|
||||
(void (*)(const br_hash_class *const *, void *))
|
||||
&br_md5sha1_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))
|
||||
&br_md5sha1_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_md5sha1_set_state
|
||||
};
|
||||
166
src/hash/multihash.c
Normal file
166
src/hash/multihash.c
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* An aggregate context that is large enough for all supported hash
|
||||
* functions.
|
||||
*/
|
||||
typedef union {
|
||||
const br_hash_class *vtable;
|
||||
br_md5_context md5;
|
||||
br_sha1_context sha1;
|
||||
br_sha224_context sha224;
|
||||
br_sha256_context sha256;
|
||||
br_sha384_context sha384;
|
||||
br_sha512_context sha512;
|
||||
} gen_hash_context;
|
||||
|
||||
/*
|
||||
* Get the offset to the state for a specific hash function within the
|
||||
* context structure. This shall be called only for the supported hash
|
||||
* functions,
|
||||
*/
|
||||
static size_t
|
||||
get_state_offset(int id)
|
||||
{
|
||||
if (id >= 5) {
|
||||
/*
|
||||
* SHA-384 has id 5, and SHA-512 has id 6. Both use
|
||||
* eight 64-bit words for their state.
|
||||
*/
|
||||
return offsetof(br_multihash_context, val_64)
|
||||
+ ((size_t)(id - 5) * (8 * sizeof(uint64_t)));
|
||||
} else {
|
||||
/*
|
||||
* MD5 has id 1, SHA-1 has id 2, SHA-224 has id 3 and
|
||||
* SHA-256 has id 4. They use 32-bit words for their
|
||||
* states (4 words for MD5, 5 for SHA-1, 8 for SHA-224
|
||||
* and 8 for SHA-256).
|
||||
*/
|
||||
unsigned x;
|
||||
|
||||
x = id - 1;
|
||||
x = ((x + (x & (x >> 1))) << 2) + (x >> 1);
|
||||
return offsetof(br_multihash_context, val_32)
|
||||
+ x * sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_multihash_zero(br_multihash_context *ctx)
|
||||
{
|
||||
/*
|
||||
* This is not standard, but yields very short and efficient code,
|
||||
* and it works "everywhere".
|
||||
*/
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_multihash_init(br_multihash_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctx->count = 0;
|
||||
for (i = 1; i <= 6; i ++) {
|
||||
const br_hash_class *hc;
|
||||
|
||||
hc = ctx->impl[i - 1];
|
||||
if (hc != NULL) {
|
||||
gen_hash_context g;
|
||||
|
||||
hc->init(&g.vtable);
|
||||
hc->state(&g.vtable,
|
||||
(unsigned char *)ctx + get_state_offset(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_multihash_update(br_multihash_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)ctx->count & 127;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 128 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
ctx->count += (uint64_t)clen;
|
||||
if (ptr == 128) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= 6; i ++) {
|
||||
const br_hash_class *hc;
|
||||
|
||||
hc = ctx->impl[i - 1];
|
||||
if (hc != NULL) {
|
||||
gen_hash_context g;
|
||||
unsigned char *state;
|
||||
|
||||
state = (unsigned char *)ctx
|
||||
+ get_state_offset(i);
|
||||
hc->set_state(&g.vtable,
|
||||
state, ctx->count - 128);
|
||||
hc->update(&g.vtable, ctx->buf, 128);
|
||||
hc->state(&g.vtable, state);
|
||||
}
|
||||
}
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
size_t
|
||||
br_multihash_out(const br_multihash_context *ctx, int id, void *dst)
|
||||
{
|
||||
const br_hash_class *hc;
|
||||
gen_hash_context g;
|
||||
const unsigned char *state;
|
||||
|
||||
hc = ctx->impl[id - 1];
|
||||
if (hc == NULL) {
|
||||
return 0;
|
||||
}
|
||||
state = (const unsigned char *)ctx + get_state_offset(id);
|
||||
hc->set_state(&g.vtable, state, ctx->count & ~(uint64_t)127);
|
||||
hc->update(&g.vtable, ctx->buf, ctx->count & (uint64_t)127);
|
||||
hc->out(&g.vtable, dst);
|
||||
return (hc->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
}
|
||||
191
src/hash/sha1.c
Normal file
191
src/hash/sha1.c
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
|
||||
#define G(B, C, D) ((B) ^ (C) ^ (D))
|
||||
#define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B)))
|
||||
#define I(B, C, D) G(B, C, D)
|
||||
|
||||
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
#define K1 ((uint32_t)0x5A827999)
|
||||
#define K2 ((uint32_t)0x6ED9EBA1)
|
||||
#define K3 ((uint32_t)0x8F1BBCDC)
|
||||
#define K4 ((uint32_t)0xCA62C1D6)
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_sha1_IV[5] = {
|
||||
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_sha1_round(const unsigned char *buf, uint32_t *val)
|
||||
{
|
||||
uint32_t m[80];
|
||||
uint32_t a, b, c, d, e;
|
||||
int i;
|
||||
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
e = val[4];
|
||||
br_range_dec32be(m, 16, buf);
|
||||
for (i = 16; i < 80; i ++) {
|
||||
uint32_t x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16];
|
||||
m[i] = ROTL(x, 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 20; i += 5) {
|
||||
e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
for (i = 20; i < 40; i += 5) {
|
||||
e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
for (i = 40; i < 60; i += 5) {
|
||||
e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
for (i = 60; i < 80; i += 5) {
|
||||
e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
val[4] += e;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_init(br_sha1_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha1_vtable;
|
||||
memcpy(cc->val, br_sha1_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_update(br_sha1_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
cc->count += (uint64_t)clen;
|
||||
if (ptr == 64) {
|
||||
br_sha1_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_out(const br_sha1_context *cc, void *dst)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val[5];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_sha1_round(buf, val);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
br_enc64be(buf + 56, cc->count << 3);
|
||||
br_sha1_round(buf, val);
|
||||
br_range_enc32be(dst, val, 5);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_sha1_state(const br_sha1_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc32be(dst, cc->val, 5);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_set_state(br_sha1_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec32be(cc->val, 5, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha1_vtable = {
|
||||
sizeof(br_sha1_context),
|
||||
BR_HASHDESC_ID(br_sha1_ID)
|
||||
| BR_HASHDESC_OUT(20)
|
||||
| BR_HASHDESC_STATE(20)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE,
|
||||
(void (*)(const br_hash_class **))&br_sha1_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))&br_sha1_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha1_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha1_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha1_set_state
|
||||
};
|
||||
285
src/hash/sha2big.c
Normal file
285
src/hash/sha2big.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
|
||||
#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
|
||||
|
||||
#define ROTR(x, n) (((uint64_t)(x) << (64 - (n))) | ((uint64_t)(x) >> (n)))
|
||||
|
||||
#define BSG5_0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||
#define BSG5_1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||
#define SSG5_0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ (uint64_t)((x) >> 7))
|
||||
#define SSG5_1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ (uint64_t)((x) >> 6))
|
||||
|
||||
static const uint64_t IV384[8] = {
|
||||
0xCBBB9D5DC1059ED8, 0x629A292A367CD507,
|
||||
0x9159015A3070DD17, 0x152FECD8F70E5939,
|
||||
0x67332667FFC00B31, 0x8EB44A8768581511,
|
||||
0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4
|
||||
};
|
||||
|
||||
static const uint64_t IV512[8] = {
|
||||
0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
|
||||
0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
|
||||
0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
|
||||
0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
|
||||
};
|
||||
|
||||
static const uint64_t K[80] = {
|
||||
0x428A2F98D728AE22, 0x7137449123EF65CD,
|
||||
0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
|
||||
0x3956C25BF348B538, 0x59F111F1B605D019,
|
||||
0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
|
||||
0xD807AA98A3030242, 0x12835B0145706FBE,
|
||||
0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
|
||||
0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1,
|
||||
0x9BDC06A725C71235, 0xC19BF174CF692694,
|
||||
0xE49B69C19EF14AD2, 0xEFBE4786384F25E3,
|
||||
0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
|
||||
0x2DE92C6F592B0275, 0x4A7484AA6EA6E483,
|
||||
0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
|
||||
0x983E5152EE66DFAB, 0xA831C66D2DB43210,
|
||||
0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
|
||||
0xC6E00BF33DA88FC2, 0xD5A79147930AA725,
|
||||
0x06CA6351E003826F, 0x142929670A0E6E70,
|
||||
0x27B70A8546D22FFC, 0x2E1B21385C26C926,
|
||||
0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
|
||||
0x650A73548BAF63DE, 0x766A0ABB3C77B2A8,
|
||||
0x81C2C92E47EDAEE6, 0x92722C851482353B,
|
||||
0xA2BFE8A14CF10364, 0xA81A664BBC423001,
|
||||
0xC24B8B70D0F89791, 0xC76C51A30654BE30,
|
||||
0xD192E819D6EF5218, 0xD69906245565A910,
|
||||
0xF40E35855771202A, 0x106AA07032BBD1B8,
|
||||
0x19A4C116B8D2D0C8, 0x1E376C085141AB53,
|
||||
0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
|
||||
0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB,
|
||||
0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
|
||||
0x748F82EE5DEFB2FC, 0x78A5636F43172F60,
|
||||
0x84C87814A1F0AB72, 0x8CC702081A6439EC,
|
||||
0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9,
|
||||
0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
|
||||
0xCA273ECEEA26619C, 0xD186B8C721C0C207,
|
||||
0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
|
||||
0x06F067AA72176FBA, 0x0A637DC5A2C898A6,
|
||||
0x113F9804BEF90DAE, 0x1B710B35131C471B,
|
||||
0x28DB77F523047D84, 0x32CAAB7B40C72493,
|
||||
0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
|
||||
0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A,
|
||||
0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817
|
||||
};
|
||||
|
||||
static void
|
||||
sha2big_round(const unsigned char *buf, uint64_t *val)
|
||||
{
|
||||
|
||||
#define SHA2BIG_STEP(A, B, C, D, E, F, G, H, j) do { \
|
||||
uint64_t T1, T2; \
|
||||
T1 = H + BSG5_1(E) + CH(E, F, G) + K[j] + w[j]; \
|
||||
T2 = BSG5_0(A) + MAJ(A, B, C); \
|
||||
D += T1; \
|
||||
H = T1 + T2; \
|
||||
} while (0)
|
||||
|
||||
int i;
|
||||
uint64_t a, b, c, d, e, f, g, h;
|
||||
uint64_t w[80];
|
||||
|
||||
br_range_dec64be(w, 16, buf);
|
||||
for (i = 16; i < 80; i ++) {
|
||||
w[i] = SSG5_1(w[i - 2]) + w[i - 7]
|
||||
+ SSG5_0(w[i - 15]) + w[i - 16];
|
||||
}
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
e = val[4];
|
||||
f = val[5];
|
||||
g = val[6];
|
||||
h = val[7];
|
||||
for (i = 0; i < 80; i += 8) {
|
||||
SHA2BIG_STEP(a, b, c, d, e, f, g, h, i + 0);
|
||||
SHA2BIG_STEP(h, a, b, c, d, e, f, g, i + 1);
|
||||
SHA2BIG_STEP(g, h, a, b, c, d, e, f, i + 2);
|
||||
SHA2BIG_STEP(f, g, h, a, b, c, d, e, i + 3);
|
||||
SHA2BIG_STEP(e, f, g, h, a, b, c, d, i + 4);
|
||||
SHA2BIG_STEP(d, e, f, g, h, a, b, c, i + 5);
|
||||
SHA2BIG_STEP(c, d, e, f, g, h, a, b, i + 6);
|
||||
SHA2BIG_STEP(b, c, d, e, f, g, h, a, i + 7);
|
||||
}
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
val[4] += e;
|
||||
val[5] += f;
|
||||
val[6] += g;
|
||||
val[7] += h;
|
||||
}
|
||||
|
||||
static void
|
||||
sha2big_update(br_sha384_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 127;
|
||||
cc->count += (uint64_t)len;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 128 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
if (ptr == 128) {
|
||||
sha2big_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sha2big_out(const br_sha384_context *cc, void *dst, int num)
|
||||
{
|
||||
unsigned char buf[128];
|
||||
uint64_t val[8];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 127;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 112) {
|
||||
memset(buf + ptr, 0, 128 - ptr);
|
||||
sha2big_round(buf, val);
|
||||
memset(buf, 0, 112);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 112 - ptr);
|
||||
}
|
||||
br_enc64be(buf + 112, cc->count >> 61);
|
||||
br_enc64be(buf + 120, cc->count << 3);
|
||||
sha2big_round(buf, val);
|
||||
br_range_enc64be(dst, val, num);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_init(br_sha384_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha384_vtable;
|
||||
memcpy(cc->val, IV384, sizeof IV384);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_update(br_sha384_context *cc, const void *data, size_t len)
|
||||
{
|
||||
sha2big_update(cc, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_out(const br_sha384_context *cc, void *dst)
|
||||
{
|
||||
sha2big_out(cc, dst, 6);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_sha384_state(const br_sha384_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc64be(dst, cc->val, 8);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_set_state(br_sha384_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec64be(cc->val, 8, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha512_init(br_sha512_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha512_vtable;
|
||||
memcpy(cc->val, IV512, sizeof IV512);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha512_out(const br_sha512_context *cc, void *dst)
|
||||
{
|
||||
sha2big_out(cc, dst, 8);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha384_vtable = {
|
||||
sizeof(br_sha384_context),
|
||||
BR_HASHDESC_ID(br_sha384_ID)
|
||||
| BR_HASHDESC_OUT(48)
|
||||
| BR_HASHDESC_STATE(64)
|
||||
| BR_HASHDESC_LBLEN(7)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE
|
||||
| BR_HASHDESC_MD_PADDING_128,
|
||||
(void (*)(const br_hash_class **))&br_sha384_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))
|
||||
&br_sha384_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha384_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha384_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha384_set_state
|
||||
};
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha512_vtable = {
|
||||
sizeof(br_sha512_context),
|
||||
BR_HASHDESC_ID(br_sha512_ID)
|
||||
| BR_HASHDESC_OUT(64)
|
||||
| BR_HASHDESC_STATE(64)
|
||||
| BR_HASHDESC_LBLEN(7)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE
|
||||
| BR_HASHDESC_MD_PADDING_128,
|
||||
(void (*)(const br_hash_class **))&br_sha512_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))
|
||||
&br_sha512_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha512_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha512_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha512_set_state
|
||||
};
|
||||
341
src/hash/sha2small.c
Normal file
341
src/hash/sha2small.c
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
|
||||
#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
|
||||
|
||||
#define ROTR(x, n) (((uint32_t)(x) << (32 - (n))) | ((uint32_t)(x) >> (n)))
|
||||
|
||||
#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ (uint32_t)((x) >> 3))
|
||||
#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ (uint32_t)((x) >> 10))
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_sha224_IV[8] = {
|
||||
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
|
||||
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_sha256_IV[8] = {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
||||
};
|
||||
|
||||
static const uint32_t K[64] = {
|
||||
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
||||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
||||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
||||
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
|
||||
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
|
||||
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
|
||||
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
|
||||
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
|
||||
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
|
||||
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
|
||||
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
|
||||
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
|
||||
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
|
||||
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
|
||||
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
|
||||
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_sha2small_round(const unsigned char *buf, uint32_t *val)
|
||||
{
|
||||
|
||||
#define SHA2_STEP(A, B, C, D, E, F, G, H, j) do { \
|
||||
uint32_t T1, T2; \
|
||||
T1 = H + BSG2_1(E) + CH(E, F, G) + K[j] + w[j]; \
|
||||
T2 = BSG2_0(A) + MAJ(A, B, C); \
|
||||
D += T1; \
|
||||
H = T1 + T2; \
|
||||
} while (0)
|
||||
|
||||
int i;
|
||||
uint32_t a, b, c, d, e, f, g, h;
|
||||
uint32_t w[64];
|
||||
|
||||
br_range_dec32be(w, 16, buf);
|
||||
for (i = 16; i < 64; i ++) {
|
||||
w[i] = SSG2_1(w[i - 2]) + w[i - 7]
|
||||
+ SSG2_0(w[i - 15]) + w[i - 16];
|
||||
}
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
e = val[4];
|
||||
f = val[5];
|
||||
g = val[6];
|
||||
h = val[7];
|
||||
for (i = 0; i < 64; i += 8) {
|
||||
SHA2_STEP(a, b, c, d, e, f, g, h, i + 0);
|
||||
SHA2_STEP(h, a, b, c, d, e, f, g, i + 1);
|
||||
SHA2_STEP(g, h, a, b, c, d, e, f, i + 2);
|
||||
SHA2_STEP(f, g, h, a, b, c, d, e, i + 3);
|
||||
SHA2_STEP(e, f, g, h, a, b, c, d, i + 4);
|
||||
SHA2_STEP(d, e, f, g, h, a, b, c, i + 5);
|
||||
SHA2_STEP(c, d, e, f, g, h, a, b, i + 6);
|
||||
SHA2_STEP(b, c, d, e, f, g, h, a, i + 7);
|
||||
}
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
val[4] += e;
|
||||
val[5] += f;
|
||||
val[6] += g;
|
||||
val[7] += h;
|
||||
|
||||
#if 0
|
||||
/* obsolete */
|
||||
#define SHA2_MEXP1(pc) do { \
|
||||
W[pc] = br_dec32be(buf + ((pc) << 2)); \
|
||||
} while (0)
|
||||
|
||||
#define SHA2_MEXP2(pc) do { \
|
||||
W[(pc) & 0x0F] = SSG2_1(W[((pc) - 2) & 0x0F]) \
|
||||
+ W[((pc) - 7) & 0x0F] \
|
||||
+ SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]; \
|
||||
} while (0)
|
||||
|
||||
#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, pc) do { \
|
||||
uint32_t t1, t2; \
|
||||
SHA2_MEXP ## n(pc); \
|
||||
t1 = h + BSG2_1(e) + CH(e, f, g) \
|
||||
+ K[pcount + (pc)] + W[(pc) & 0x0F]; \
|
||||
t2 = BSG2_0(a) + MAJ(a, b, c); \
|
||||
d += t1; \
|
||||
h = t1 + t2; \
|
||||
} while (0)
|
||||
|
||||
#define SHA2_STEP1(a, b, c, d, e, f, g, h, pc) \
|
||||
SHA2_STEPn(1, a, b, c, d, e, f, g, h, pc)
|
||||
#define SHA2_STEP2(a, b, c, d, e, f, g, h, pc) \
|
||||
SHA2_STEPn(2, a, b, c, d, e, f, g, h, pc)
|
||||
|
||||
uint32_t A, B, C, D, E, F, G, H;
|
||||
uint32_t W[16];
|
||||
unsigned pcount;
|
||||
|
||||
A = val[0];
|
||||
B = val[1];
|
||||
C = val[2];
|
||||
D = val[3];
|
||||
E = val[4];
|
||||
F = val[5];
|
||||
G = val[6];
|
||||
H = val[7];
|
||||
pcount = 0;
|
||||
SHA2_STEP1(A, B, C, D, E, F, G, H, 0);
|
||||
SHA2_STEP1(H, A, B, C, D, E, F, G, 1);
|
||||
SHA2_STEP1(G, H, A, B, C, D, E, F, 2);
|
||||
SHA2_STEP1(F, G, H, A, B, C, D, E, 3);
|
||||
SHA2_STEP1(E, F, G, H, A, B, C, D, 4);
|
||||
SHA2_STEP1(D, E, F, G, H, A, B, C, 5);
|
||||
SHA2_STEP1(C, D, E, F, G, H, A, B, 6);
|
||||
SHA2_STEP1(B, C, D, E, F, G, H, A, 7);
|
||||
SHA2_STEP1(A, B, C, D, E, F, G, H, 8);
|
||||
SHA2_STEP1(H, A, B, C, D, E, F, G, 9);
|
||||
SHA2_STEP1(G, H, A, B, C, D, E, F, 10);
|
||||
SHA2_STEP1(F, G, H, A, B, C, D, E, 11);
|
||||
SHA2_STEP1(E, F, G, H, A, B, C, D, 12);
|
||||
SHA2_STEP1(D, E, F, G, H, A, B, C, 13);
|
||||
SHA2_STEP1(C, D, E, F, G, H, A, B, 14);
|
||||
SHA2_STEP1(B, C, D, E, F, G, H, A, 15);
|
||||
for (pcount = 16; pcount < 64; pcount += 16) {
|
||||
SHA2_STEP2(A, B, C, D, E, F, G, H, 0);
|
||||
SHA2_STEP2(H, A, B, C, D, E, F, G, 1);
|
||||
SHA2_STEP2(G, H, A, B, C, D, E, F, 2);
|
||||
SHA2_STEP2(F, G, H, A, B, C, D, E, 3);
|
||||
SHA2_STEP2(E, F, G, H, A, B, C, D, 4);
|
||||
SHA2_STEP2(D, E, F, G, H, A, B, C, 5);
|
||||
SHA2_STEP2(C, D, E, F, G, H, A, B, 6);
|
||||
SHA2_STEP2(B, C, D, E, F, G, H, A, 7);
|
||||
SHA2_STEP2(A, B, C, D, E, F, G, H, 8);
|
||||
SHA2_STEP2(H, A, B, C, D, E, F, G, 9);
|
||||
SHA2_STEP2(G, H, A, B, C, D, E, F, 10);
|
||||
SHA2_STEP2(F, G, H, A, B, C, D, E, 11);
|
||||
SHA2_STEP2(E, F, G, H, A, B, C, D, 12);
|
||||
SHA2_STEP2(D, E, F, G, H, A, B, C, 13);
|
||||
SHA2_STEP2(C, D, E, F, G, H, A, B, 14);
|
||||
SHA2_STEP2(B, C, D, E, F, G, H, A, 15);
|
||||
}
|
||||
val[0] += A;
|
||||
val[1] += B;
|
||||
val[2] += C;
|
||||
val[3] += D;
|
||||
val[4] += E;
|
||||
val[5] += F;
|
||||
val[6] += G;
|
||||
val[7] += H;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
sha2small_update(br_sha224_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
cc->count += (uint64_t)len;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
if (ptr == 64) {
|
||||
br_sha2small_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sha2small_out(const br_sha224_context *cc, void *dst, int num)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val[8];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_sha2small_round(buf, val);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
br_enc64be(buf + 56, cc->count << 3);
|
||||
br_sha2small_round(buf, val);
|
||||
br_range_enc32be(dst, val, num);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_init(br_sha224_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha224_vtable;
|
||||
memcpy(cc->val, br_sha224_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_update(br_sha224_context *cc, const void *data, size_t len)
|
||||
{
|
||||
sha2small_update(cc, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_out(const br_sha224_context *cc, void *dst)
|
||||
{
|
||||
sha2small_out(cc, dst, 7);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_sha224_state(const br_sha224_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc32be(dst, cc->val, 8);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_set_state(br_sha224_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec32be(cc->val, 8, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha256_init(br_sha256_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha256_vtable;
|
||||
memcpy(cc->val, br_sha256_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha256_out(const br_sha256_context *cc, void *dst)
|
||||
{
|
||||
sha2small_out(cc, dst, 8);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha224_vtable = {
|
||||
sizeof(br_sha224_context),
|
||||
BR_HASHDESC_ID(br_sha224_ID)
|
||||
| BR_HASHDESC_OUT(28)
|
||||
| BR_HASHDESC_STATE(32)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE,
|
||||
(void (*)(const br_hash_class **))&br_sha224_init,
|
||||
(void (*)(const br_hash_class **,
|
||||
const void *, size_t))&br_sha224_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha224_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha224_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha224_set_state
|
||||
};
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha256_vtable = {
|
||||
sizeof(br_sha256_context),
|
||||
BR_HASHDESC_ID(br_sha256_ID)
|
||||
| BR_HASHDESC_OUT(32)
|
||||
| BR_HASHDESC_STATE(32)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE,
|
||||
(void (*)(const br_hash_class **))&br_sha256_init,
|
||||
(void (*)(const br_hash_class **,
|
||||
const void *, size_t))&br_sha256_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha256_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha256_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha256_set_state
|
||||
};
|
||||
1546
src/inner.h
Normal file
1546
src/inner.h
Normal file
File diff suppressed because it is too large
Load diff
46
src/int/i31_add.c
Normal file
46
src/int/i31_add.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 63) >> 5;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw + bw + cc;
|
||||
cc = naw >> 31;
|
||||
a[u] = MUX(ctl, naw & (uint32_t)0x7FFFFFFF, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
44
src/int/i31_bitlen.c
Normal file
44
src/int/i31_bitlen.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i31_bit_length(uint32_t *x, size_t xlen)
|
||||
{
|
||||
uint32_t tw, twk;
|
||||
|
||||
tw = 0;
|
||||
twk = 0;
|
||||
while (xlen -- > 0) {
|
||||
uint32_t w, c;
|
||||
|
||||
c = EQ(tw, 0);
|
||||
w = x[xlen];
|
||||
tw = MUX(c, w, tw);
|
||||
twk = MUX(c, (uint32_t)xlen, twk);
|
||||
}
|
||||
return (twk << 5) + BIT_LENGTH(tw);
|
||||
}
|
||||
124
src/int/i31_decmod.c
Normal file
124
src/int/i31_decmod.c
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i31_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m)
|
||||
{
|
||||
/*
|
||||
* Two-pass algorithm: in the first pass, we determine whether the
|
||||
* value fits; in the second pass, we do the actual write.
|
||||
*
|
||||
* During the first pass, 'r' contains the comparison result so
|
||||
* far:
|
||||
* 0x00000000 value is equal to the modulus
|
||||
* 0x00000001 value is greater than the modulus
|
||||
* 0xFFFFFFFF value is lower than the modulus
|
||||
*
|
||||
* Since we iterate starting with the least significant bytes (at
|
||||
* the end of src[]), each new comparison overrides the previous
|
||||
* except when the comparison yields 0 (equal).
|
||||
*
|
||||
* During the second pass, 'r' is either 0xFFFFFFFF (value fits)
|
||||
* or 0x00000000 (value does not fit).
|
||||
*
|
||||
* We must iterate over all bytes of the source, _and_ possibly
|
||||
* some extra virutal bytes (with value 0) so as to cover the
|
||||
* complete modulus as well. We also add 4 such extra bytes beyond
|
||||
* the modulus length because it then guarantees that no accumulated
|
||||
* partial word remains to be processed.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t mlen, tlen;
|
||||
int pass;
|
||||
uint32_t r;
|
||||
|
||||
buf = src;
|
||||
mlen = (m[0] + 31) >> 5;
|
||||
tlen = (mlen << 2);
|
||||
if (tlen < len) {
|
||||
tlen = len;
|
||||
}
|
||||
tlen += 4;
|
||||
r = 0;
|
||||
for (pass = 0; pass < 2; pass ++) {
|
||||
size_t u, v;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
v = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
for (u = 0; u < tlen; u ++) {
|
||||
uint32_t b;
|
||||
|
||||
if (u < len) {
|
||||
b = buf[len - 1 - u];
|
||||
} else {
|
||||
b = 0;
|
||||
}
|
||||
acc |= (b << acc_len);
|
||||
acc_len += 8;
|
||||
if (acc_len >= 31) {
|
||||
uint32_t xw;
|
||||
|
||||
xw = acc & (uint32_t)0x7FFFFFFF;
|
||||
acc_len -= 31;
|
||||
acc = b >> (8 - acc_len);
|
||||
if (v <= mlen) {
|
||||
if (pass) {
|
||||
x[v] = r & xw;
|
||||
} else {
|
||||
uint32_t cc;
|
||||
|
||||
cc = (uint32_t)CMP(xw, m[v]);
|
||||
r = MUX(EQ(cc, 0), r, cc);
|
||||
}
|
||||
} else {
|
||||
if (!pass) {
|
||||
r = MUX(EQ(xw, 0), r, 1);
|
||||
}
|
||||
}
|
||||
v ++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When we reach this point at the end of the first pass:
|
||||
* r is either 0, 1 or -1; we want to set r to 0 if it
|
||||
* is equal to 0 or 1, and leave it to -1 otherwise.
|
||||
*
|
||||
* When we reach this point at the end of the second pass:
|
||||
* r is either 0 or -1; we want to leave that value
|
||||
* untouched. This is a subcase of the previous.
|
||||
*/
|
||||
r >>= 1;
|
||||
r |= (r << 1);
|
||||
}
|
||||
|
||||
x[0] = m[0];
|
||||
return r & (uint32_t)1;
|
||||
}
|
||||
57
src/int/i31_decode.c
Normal file
57
src/int/i31_decode.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_decode(uint32_t *x, const void *src, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t u, v;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
buf = src;
|
||||
u = len;
|
||||
v = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (u -- > 0) {
|
||||
uint32_t b;
|
||||
|
||||
b = buf[u];
|
||||
acc |= (b << acc_len);
|
||||
acc_len += 8;
|
||||
if (acc_len >= 31) {
|
||||
x[v ++] = acc & (uint32_t)0x7FFFFFFF;
|
||||
acc_len -= 31;
|
||||
acc = b >> (8 - acc_len);
|
||||
}
|
||||
}
|
||||
if (acc_len != 0) {
|
||||
x[v ++] = acc;
|
||||
}
|
||||
x[0] = br_i31_bit_length(x + 1, v - 1);
|
||||
}
|
||||
103
src/int/i31_decred.c
Normal file
103
src/int/i31_decred.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_decode_reduce(uint32_t *x,
|
||||
const void *src, size_t len, const uint32_t *m)
|
||||
{
|
||||
uint32_t m_ebitlen, m_rbitlen;
|
||||
size_t mblen, k;
|
||||
const unsigned char *buf;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
/*
|
||||
* Get the encoded bit length.
|
||||
*/
|
||||
m_ebitlen = m[0];
|
||||
|
||||
/*
|
||||
* Special case for an invalid (null) modulus.
|
||||
*/
|
||||
if (m_ebitlen == 0) {
|
||||
x[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the destination.
|
||||
*/
|
||||
br_i31_zero(x, m_ebitlen);
|
||||
|
||||
/*
|
||||
* First decode directly as many bytes as possible. This requires
|
||||
* computing the actual bit length.
|
||||
*/
|
||||
m_rbitlen = m_ebitlen >> 5;
|
||||
m_rbitlen = (m_ebitlen & 31) + (m_rbitlen << 5) - m_rbitlen;
|
||||
mblen = (m_rbitlen + 7) >> 3;
|
||||
k = mblen - 1;
|
||||
if (k >= len) {
|
||||
br_i31_decode(x, src, len);
|
||||
x[0] = m_ebitlen;
|
||||
return;
|
||||
}
|
||||
buf = src;
|
||||
br_i31_decode(x, buf, k);
|
||||
x[0] = m_ebitlen;
|
||||
|
||||
/*
|
||||
* Input remaining bytes, using 31-bit words.
|
||||
*/
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (k < len) {
|
||||
uint32_t v;
|
||||
|
||||
v = buf[k ++];
|
||||
if (acc_len >= 23) {
|
||||
acc_len -= 23;
|
||||
acc <<= (8 - acc_len);
|
||||
acc |= v >> acc_len;
|
||||
br_i31_muladd_small(x, acc, m);
|
||||
acc = v & (0xFF >> (8 - acc_len));
|
||||
} else {
|
||||
acc = (acc << 8) | v;
|
||||
acc_len += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have some bits accumulated. We then perform a shift to
|
||||
* be able to inject these bits as a full 31-bit word.
|
||||
*/
|
||||
if (acc_len != 0) {
|
||||
acc = (acc | (x[1] << acc_len)) & 0x7FFFFFFF;
|
||||
br_i31_rshift(x, 31 - acc_len);
|
||||
br_i31_muladd_small(x, acc, m);
|
||||
}
|
||||
}
|
||||
79
src/int/i31_encode.c
Normal file
79
src/int/i31_encode.c
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_encode(void *dst, size_t len, const uint32_t *x)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t k, xlen;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
xlen = (x[0] + 31) >> 5;
|
||||
if (xlen == 0) {
|
||||
memset(dst, 0, len);
|
||||
return;
|
||||
}
|
||||
buf = (unsigned char *)dst + len;
|
||||
k = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (len != 0) {
|
||||
uint32_t w;
|
||||
|
||||
w = (k <= xlen) ? x[k] : 0;
|
||||
k ++;
|
||||
if (acc_len == 0) {
|
||||
acc = w;
|
||||
acc_len = 31;
|
||||
} else {
|
||||
uint32_t z;
|
||||
|
||||
z = acc | (w << acc_len);
|
||||
acc_len --;
|
||||
acc = w >> (31 - acc_len);
|
||||
if (len >= 4) {
|
||||
buf -= 4;
|
||||
len -= 4;
|
||||
br_enc32be(buf, z);
|
||||
} else {
|
||||
switch (len) {
|
||||
case 3:
|
||||
buf[-3] = (unsigned char)(z >> 16);
|
||||
/* fall through */
|
||||
case 2:
|
||||
buf[-2] = (unsigned char)(z >> 8);
|
||||
/* fall through */
|
||||
case 1:
|
||||
buf[-1] = (unsigned char)z;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/int/i31_fmont.c
Normal file
60
src/int/i31_fmont.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i)
|
||||
{
|
||||
size_t len, u, v;
|
||||
|
||||
len = (m[0] + 31) >> 5;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t f;
|
||||
uint64_t cc;
|
||||
|
||||
f = (x[1] * m0i) & 0x7FFFFFFF;
|
||||
cc = 0;
|
||||
for (v = 0; v < len; v ++) {
|
||||
uint64_t z;
|
||||
|
||||
z = (uint64_t)x[v + 1] + MUL31(f, m[v + 1]) + cc;
|
||||
cc = z >> 31;
|
||||
if (v != 0) {
|
||||
x[v] = (uint32_t)z & 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
x[len] = (uint32_t)cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have to do an extra subtraction, but only if the
|
||||
* value in x[] is indeed greater than or equal to that of m[],
|
||||
* which is why we must do two calls (first call computes the
|
||||
* carry, second call performs the subtraction only if the carry
|
||||
* is 0).
|
||||
*/
|
||||
br_i31_sub(x, m, NOT(br_i31_sub(x, m, 0)));
|
||||
}
|
||||
39
src/int/i31_iszero.c
Normal file
39
src/int/i31_iszero.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i31_iszero(const uint32_t *x)
|
||||
{
|
||||
uint32_t z;
|
||||
size_t u;
|
||||
|
||||
z = 0;
|
||||
for (u = (x[0] + 31) >> 5; u > 0; u --) {
|
||||
z |= x[u];
|
||||
}
|
||||
return ~(z | -z) >> 31;
|
||||
}
|
||||
65
src/int/i31_modpow.c
Normal file
65
src/int/i31_modpow.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_modpow(uint32_t *x,
|
||||
const unsigned char *e, size_t elen,
|
||||
const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2)
|
||||
{
|
||||
size_t mlen;
|
||||
uint32_t k;
|
||||
|
||||
/*
|
||||
* 'mlen' is the length of m[] expressed in bytes (including
|
||||
* the "bit length" first field).
|
||||
*/
|
||||
mlen = ((m[0] + 63) >> 5) * sizeof m[0];
|
||||
|
||||
/*
|
||||
* Throughout the algorithm:
|
||||
* -- t1[] is in Montgomery representation; it contains x, x^2,
|
||||
* x^4, x^8...
|
||||
* -- The result is accumulated, in normal representation, in
|
||||
* the x[] array.
|
||||
* -- t2[] is used as destination buffer for each multiplication.
|
||||
*
|
||||
* Note that there is no need to call br_i32_from_monty().
|
||||
*/
|
||||
memcpy(t1, x, mlen);
|
||||
br_i31_to_monty(t1, m);
|
||||
br_i31_zero(x, m[0]);
|
||||
x[1] = 1;
|
||||
for (k = 0; k < ((uint32_t)elen << 3); k ++) {
|
||||
uint32_t ctl;
|
||||
|
||||
ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1;
|
||||
br_i31_montymul(t2, x, t1, m, m0i);
|
||||
CCOPY(ctl, x, t2, mlen);
|
||||
br_i31_montymul(t2, t1, t1, m, m0i);
|
||||
memcpy(t1, t2, mlen);
|
||||
}
|
||||
}
|
||||
93
src/int/i31_montmul.c
Normal file
93
src/int/i31_montmul.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
|
||||
const uint32_t *m, uint32_t m0i)
|
||||
{
|
||||
size_t len, len4, u, v;
|
||||
uint64_t dh;
|
||||
|
||||
len = (m[0] + 31) >> 5;
|
||||
len4 = len & ~(size_t)3;
|
||||
br_i32_zero(d, m[0]);
|
||||
dh = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t f, xu;
|
||||
uint64_t r, zh;
|
||||
|
||||
xu = x[u + 1];
|
||||
f = ((d[1] + x[u + 1] * y[1]) * m0i) & 0x7FFFFFFF;
|
||||
|
||||
r = 0;
|
||||
for (v = 0; v < len4; v += 4) {
|
||||
uint64_t z;
|
||||
|
||||
z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1])
|
||||
+ MUL31(f, m[v + 1]) + r;
|
||||
r = z >> 31;
|
||||
d[v + 0] = (uint32_t)z & 0x7FFFFFFF;
|
||||
z = (uint64_t)d[v + 2] + MUL31(xu, y[v + 2])
|
||||
+ MUL31(f, m[v + 2]) + r;
|
||||
r = z >> 31;
|
||||
d[v + 1] = (uint32_t)z & 0x7FFFFFFF;
|
||||
z = (uint64_t)d[v + 3] + MUL31(xu, y[v + 3])
|
||||
+ MUL31(f, m[v + 3]) + r;
|
||||
r = z >> 31;
|
||||
d[v + 2] = (uint32_t)z & 0x7FFFFFFF;
|
||||
z = (uint64_t)d[v + 4] + MUL31(xu, y[v + 4])
|
||||
+ MUL31(f, m[v + 4]) + r;
|
||||
r = z >> 31;
|
||||
d[v + 3] = (uint32_t)z & 0x7FFFFFFF;
|
||||
}
|
||||
for (; v < len; v ++) {
|
||||
uint64_t z;
|
||||
|
||||
z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1])
|
||||
+ MUL31(f, m[v + 1]) + r;
|
||||
r = z >> 31;
|
||||
d[v] = (uint32_t)z & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
zh = dh + r;
|
||||
d[len] = (uint32_t)zh & 0x7FFFFFFF;
|
||||
dh = zh >> 31;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must write back the bit length because it was overwritten in
|
||||
* the loop (not overwriting it would require a test in the loop,
|
||||
* which would yield bigger and slower code).
|
||||
*/
|
||||
d[0] = m[0];
|
||||
|
||||
/*
|
||||
* d[] may still be greater than m[] at that point; notably, the
|
||||
* 'dh' word may be non-zero.
|
||||
*/
|
||||
br_i31_sub(d, m, NEQ(dh, 0) | NOT(br_i31_sub(d, m, 0)));
|
||||
}
|
||||
52
src/int/i31_mulacc.c
Normal file
52
src/int/i31_mulacc.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
size_t alen, blen, u;
|
||||
|
||||
alen = (a[0] + 31) >> 5;
|
||||
blen = (b[0] + 31) >> 5;
|
||||
d[0] = a[0] + b[0];
|
||||
for (u = 0; u < blen; u ++) {
|
||||
uint32_t f;
|
||||
size_t v;
|
||||
uint64_t cc;
|
||||
|
||||
f = b[1 + u];
|
||||
cc = 0;
|
||||
for (v = 0; v < alen; v ++) {
|
||||
uint64_t z;
|
||||
|
||||
z = (uint64_t)d[1 + u + v] + MUL31(f, a[1 + v]) + cc;
|
||||
cc = z >> 31;
|
||||
d[1 + u + v] = (uint32_t)z & 0x7FFFFFFF;
|
||||
}
|
||||
d[1 + u + alen] = (uint32_t)cc;
|
||||
}
|
||||
}
|
||||
157
src/int/i31_muladd.c
Normal file
157
src/int/i31_muladd.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m)
|
||||
{
|
||||
uint32_t m_bitlen;
|
||||
unsigned mblr;
|
||||
size_t u, mlen;
|
||||
uint32_t a0, a1, b0, hi, g, q, tb;
|
||||
uint32_t under, over;
|
||||
uint32_t cc;
|
||||
|
||||
/*
|
||||
* We can test on the modulus bit length since we accept to
|
||||
* leak that length.
|
||||
*/
|
||||
m_bitlen = m[0];
|
||||
if (m_bitlen == 0) {
|
||||
return;
|
||||
}
|
||||
if (m_bitlen <= 31) {
|
||||
uint32_t hi, lo;
|
||||
|
||||
hi = x[1] >> 1;
|
||||
lo = (x[1] << 31) | z;
|
||||
x[1] = br_rem(hi, lo, m[1]);
|
||||
return;
|
||||
}
|
||||
mlen = (m_bitlen + 31) >> 5;
|
||||
mblr = (unsigned)m_bitlen & 31;
|
||||
|
||||
/*
|
||||
* Principle: we estimate the quotient (x*2^31+z)/m by
|
||||
* doing a 64/32 division with the high words.
|
||||
*
|
||||
* Let:
|
||||
* w = 2^31
|
||||
* a = (w*a0 + a1) * w^N + a2
|
||||
* b = b0 * w^N + b2
|
||||
* such that:
|
||||
* 0 <= a0 < w
|
||||
* 0 <= a1 < w
|
||||
* 0 <= a2 < w^N
|
||||
* w/2 <= b0 < w
|
||||
* 0 <= b2 < w^N
|
||||
* a < w*b
|
||||
* I.e. the two top words of a are a0:a1, the top word of b is
|
||||
* b0, we ensured that b0 is "full" (high bit set), and a is
|
||||
* such that the quotient q = a/b fits on one word (0 <= q < w).
|
||||
*
|
||||
* If a = b*q + r (with 0 <= r < q), we can estimate q by
|
||||
* doing an Euclidean division on the top words:
|
||||
* a0*w+a1 = b0*u + v (with 0 <= v < w)
|
||||
* Then the following holds:
|
||||
* 0 <= u <= w
|
||||
* u-2 <= q <= u
|
||||
*/
|
||||
hi = x[mlen];
|
||||
if (mblr == 0) {
|
||||
a0 = x[mlen];
|
||||
memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
|
||||
x[1] = z;
|
||||
a1 = x[mlen];
|
||||
b0 = m[mlen];
|
||||
} else {
|
||||
a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr))
|
||||
& 0x7FFFFFFF;
|
||||
memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
|
||||
x[1] = z;
|
||||
a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr))
|
||||
& 0x7FFFFFFF;
|
||||
b0 = ((m[mlen] << (31 - mblr)) | (m[mlen - 1] >> mblr))
|
||||
& 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* We estimate a divisor q. If the quotient returned by br_div()
|
||||
* is g:
|
||||
* -- If a0 == b0 then g == 0; we want q = 0x7FFFFFFF.
|
||||
* -- Otherwise:
|
||||
* -- if g == 0 then we set q = 0;
|
||||
* -- otherwise, we set q = g - 1.
|
||||
* The properties described above then ensure that the true
|
||||
* quotient is q-1, q or q+1.
|
||||
*
|
||||
* Take care that a0, a1 and b0 are 31-bit words, not 32-bit. We
|
||||
* must adjust the parameters to br_div() accordingly.
|
||||
*/
|
||||
g = br_div(a0 >> 1, a1 | (a0 << 31), b0);
|
||||
q = MUX(EQ(a0, b0), 0x7FFFFFFF, MUX(EQ(g, 0), 0, g - 1));
|
||||
|
||||
/*
|
||||
* We subtract q*m from x (with the extra high word of value 'hi').
|
||||
* Since q may be off by 1 (in either direction), we may have to
|
||||
* add or subtract m afterwards.
|
||||
*
|
||||
* The 'tb' flag will be true (1) at the end of the loop if the
|
||||
* result is greater than or equal to the modulus (not counting
|
||||
* 'hi' or the carry).
|
||||
*/
|
||||
cc = 0;
|
||||
tb = 1;
|
||||
for (u = 1; u <= mlen; u ++) {
|
||||
uint32_t mw, zw, xw, nxw;
|
||||
uint64_t zl;
|
||||
|
||||
mw = m[u];
|
||||
zl = MUL31(mw, q) + cc;
|
||||
cc = (uint32_t)(zl >> 31);
|
||||
zw = (uint32_t)zl & (uint32_t)0x7FFFFFFF;
|
||||
xw = x[u];
|
||||
nxw = xw - zw;
|
||||
cc += nxw >> 31;
|
||||
nxw &= 0x7FFFFFFF;
|
||||
x[u] = nxw;
|
||||
tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we underestimated q, then either cc < hi (one extra bit
|
||||
* beyond the top array word), or cc == hi and tb is true (no
|
||||
* extra bit, but the result is not lower than the modulus). In
|
||||
* these cases we must subtract m once.
|
||||
*
|
||||
* Otherwise, we may have overestimated, which will show as
|
||||
* cc > hi (thus a negative result). Correction is adding m once.
|
||||
*/
|
||||
over = GT(cc, hi);
|
||||
under = ~over & (tb | LT(cc, hi));
|
||||
br_i31_add(x, m, over);
|
||||
br_i31_sub(x, m, under);
|
||||
}
|
||||
39
src/int/i31_ninv31.c
Normal file
39
src/int/i31_ninv31.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i31_ninv31(uint32_t x)
|
||||
{
|
||||
uint32_t y;
|
||||
|
||||
y = 2 - x;
|
||||
y *= 2 - y * x;
|
||||
y *= 2 - y * x;
|
||||
y *= 2 - y * x;
|
||||
y *= 2 - y * x;
|
||||
return MUX(x & 1, -y, 0) & 0x7FFFFFFF;
|
||||
}
|
||||
66
src/int/i31_reduce.c
Normal file
66
src/int/i31_reduce.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m)
|
||||
{
|
||||
uint32_t m_bitlen, a_bitlen;
|
||||
size_t mlen, alen, u;
|
||||
|
||||
m_bitlen = m[0];
|
||||
mlen = (m_bitlen + 31) >> 5;
|
||||
|
||||
x[0] = m_bitlen;
|
||||
if (m_bitlen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the source is shorter, then simply copy all words from a[]
|
||||
* and zero out the upper words.
|
||||
*/
|
||||
a_bitlen = a[0];
|
||||
alen = (a_bitlen + 31) >> 5;
|
||||
if (a_bitlen < m_bitlen) {
|
||||
memcpy(x + 1, a + 1, alen * sizeof *a);
|
||||
for (u = alen; u < mlen; u ++) {
|
||||
x[u + 1] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The source length is at least equal to that of the modulus.
|
||||
* We must thus copy N-1 words, and input the remaining words
|
||||
* one by one.
|
||||
*/
|
||||
memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a);
|
||||
x[mlen] = 0;
|
||||
for (u = 1 + alen - mlen; u > 0; u --) {
|
||||
br_i31_muladd_small(x, a[u], m);
|
||||
}
|
||||
}
|
||||
47
src/int/i31_rshift.c
Normal file
47
src/int/i31_rshift.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_rshift(uint32_t *x, int count)
|
||||
{
|
||||
size_t u, len;
|
||||
uint32_t r;
|
||||
|
||||
len = (x[0] + 31) >> 5;
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
r = x[1] >> count;
|
||||
for (u = 2; u <= len; u ++) {
|
||||
uint32_t w;
|
||||
|
||||
w = x[u];
|
||||
x[u - 1] = ((w << (31 - count)) | r) & 0x7FFFFFFF;
|
||||
r = w >> count;
|
||||
}
|
||||
x[len] = r;
|
||||
}
|
||||
46
src/int/i31_sub.c
Normal file
46
src/int/i31_sub.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 63) >> 5;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw - bw - cc;
|
||||
cc = naw >> 31;
|
||||
a[u] = MUX(ctl, naw & 0x7FFFFFFF, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
36
src/int/i31_tmont.c
Normal file
36
src/int/i31_tmont.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i31_to_monty(uint32_t *x, const uint32_t *m)
|
||||
{
|
||||
uint32_t k;
|
||||
|
||||
for (k = (m[0] + 31) >> 5; k > 0; k --) {
|
||||
br_i31_muladd_small(x, 0, m);
|
||||
}
|
||||
}
|
||||
51
src/int/i32_add.c
Normal file
51
src/int/i32_add.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 63) >> 5;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw + bw + cc;
|
||||
|
||||
/*
|
||||
* Carry is 1 if naw < aw. Carry is also 1 if naw == aw
|
||||
* AND the carry was already 1.
|
||||
*/
|
||||
cc = (cc & EQ(naw, aw)) | LT(naw, aw);
|
||||
a[u] = MUX(ctl, naw, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
44
src/int/i32_bitlen.c
Normal file
44
src/int/i32_bitlen.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i32_bit_length(uint32_t *x, size_t xlen)
|
||||
{
|
||||
uint32_t tw, twk;
|
||||
|
||||
tw = 0;
|
||||
twk = 0;
|
||||
while (xlen -- > 0) {
|
||||
uint32_t w, c;
|
||||
|
||||
c = EQ(tw, 0);
|
||||
w = x[xlen];
|
||||
tw = MUX(c, w, tw);
|
||||
twk = MUX(c, (uint32_t)xlen, twk);
|
||||
}
|
||||
return (twk << 5) + BIT_LENGTH(tw);
|
||||
}
|
||||
77
src/int/i32_decmod.c
Normal file
77
src/int/i32_decmod.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i32_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
uint32_t r;
|
||||
size_t u, v, mlen;
|
||||
|
||||
buf = src;
|
||||
|
||||
/*
|
||||
* First pass: determine whether the value fits. The 'r' value
|
||||
* will contain the comparison result, as 0x00000000 (value is
|
||||
* equal to the modulus), 0x00000001 (value is greater than the
|
||||
* modulus), or 0xFFFFFFFF (value is lower than the modulus).
|
||||
*/
|
||||
mlen = (m[0] + 7) >> 3;
|
||||
r = 0;
|
||||
for (u = (mlen > len) ? mlen : len; u > 0; u --) {
|
||||
uint32_t mb, xb;
|
||||
|
||||
v = u - 1;
|
||||
if (v >= mlen) {
|
||||
mb = 0;
|
||||
} else {
|
||||
mb = (m[1 + (v >> 2)] >> ((v & 3) << 3)) & 0xFF;
|
||||
}
|
||||
if (v >= len) {
|
||||
xb = 0;
|
||||
} else {
|
||||
xb = buf[len - u];
|
||||
}
|
||||
r = MUX(EQ(r, 0), (uint32_t)CMP(xb, mb), r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only r == 0xFFFFFFFF is acceptable. We want to set r to 0xFF if
|
||||
* the value fits, 0x00 otherwise.
|
||||
*/
|
||||
r >>= 24;
|
||||
br_i32_zero(x, m[0]);
|
||||
u = (mlen > len) ? len : mlen;
|
||||
while (u > 0) {
|
||||
uint32_t xb;
|
||||
|
||||
xb = buf[len - u] & r;
|
||||
u --;
|
||||
x[1 + (u >> 2)] |= xb << ((u & 3) << 3);
|
||||
}
|
||||
return r >> 7;
|
||||
}
|
||||
63
src/int/i32_decode.c
Normal file
63
src/int/i32_decode.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_decode(uint32_t *x, const void *src, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t u, v;
|
||||
|
||||
buf = src;
|
||||
u = len;
|
||||
v = 1;
|
||||
for (;;) {
|
||||
if (u < 4) {
|
||||
uint32_t w;
|
||||
|
||||
if (u < 2) {
|
||||
if (u == 0) {
|
||||
break;
|
||||
} else {
|
||||
w = buf[0];
|
||||
}
|
||||
} else {
|
||||
if (u == 2) {
|
||||
w = br_dec16be(buf);
|
||||
} else {
|
||||
w = ((uint32_t)buf[0] << 16)
|
||||
| br_dec16be(buf + 1);
|
||||
}
|
||||
}
|
||||
x[v ++] = w;
|
||||
break;
|
||||
} else {
|
||||
u -= 4;
|
||||
x[v ++] = br_dec32be(buf + u);
|
||||
}
|
||||
}
|
||||
x[0] = br_i32_bit_length(x + 1, v - 1);
|
||||
}
|
||||
107
src/int/i32_decred.c
Normal file
107
src/int/i32_decred.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_decode_reduce(uint32_t *x,
|
||||
const void *src, size_t len, const uint32_t *m)
|
||||
{
|
||||
uint32_t m_bitlen;
|
||||
size_t mblen, k, q;
|
||||
const unsigned char *buf;
|
||||
|
||||
m_bitlen = m[0];
|
||||
|
||||
/*
|
||||
* Special case for an invalid modulus.
|
||||
*/
|
||||
if (m_bitlen == 0) {
|
||||
x[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the destination.
|
||||
*/
|
||||
br_i32_zero(x, m_bitlen);
|
||||
|
||||
/*
|
||||
* First decode directly as many bytes as possible without
|
||||
* reduction, taking care to leave a number of bytes which
|
||||
* is a multiple of 4.
|
||||
*/
|
||||
mblen = (m_bitlen + 7) >> 3;
|
||||
k = mblen - 1;
|
||||
|
||||
/*
|
||||
* Up to k bytes can be safely decoded.
|
||||
*/
|
||||
if (k >= len) {
|
||||
br_i32_decode(x, src, len);
|
||||
x[0] = m_bitlen;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to first inject some bytes with direct decoding,
|
||||
* then extra bytes by whole 32-bit words. First compute
|
||||
* the size that should be injected that way.
|
||||
*/
|
||||
buf = src;
|
||||
q = (len - k + 3) & ~(size_t)3;
|
||||
|
||||
/*
|
||||
* It may happen that this is more than what we already have
|
||||
* (by at most 3 bytes). Such a case may happen only with
|
||||
* a very short modulus. In that case, we must process the first
|
||||
* bytes "manually".
|
||||
*/
|
||||
if (q > len) {
|
||||
int i;
|
||||
uint32_t w;
|
||||
|
||||
w = 0;
|
||||
for (i = 0; i < 4; i ++) {
|
||||
w <<= 8;
|
||||
if (q <= len) {
|
||||
w |= buf[len - q];
|
||||
}
|
||||
q --;
|
||||
}
|
||||
br_i32_muladd_small(x, w, m);
|
||||
} else {
|
||||
br_i32_decode(x, buf, len - q);
|
||||
x[0] = m_bitlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* At that point, we have exactly q bytes to inject, and q is
|
||||
* a multiple of 4.
|
||||
*/
|
||||
for (k = len - q; k < len; k += 4) {
|
||||
br_i32_muladd_small(x, br_dec32be(buf + k), m);
|
||||
}
|
||||
}
|
||||
56
src/int/i32_div32.c
Normal file
56
src/int/i32_div32.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r)
|
||||
{
|
||||
// TODO: optimize this
|
||||
uint32_t q;
|
||||
uint32_t ch, cf;
|
||||
int k;
|
||||
|
||||
q = 0;
|
||||
ch = EQ(hi, d);
|
||||
hi = MUX(ch, 0, hi);
|
||||
for (k = 31; k > 0; k --) {
|
||||
int j;
|
||||
uint32_t w, ctl, hi2, lo2;
|
||||
|
||||
j = 32 - k;
|
||||
w = (hi << j) | (lo >> k);
|
||||
ctl = GE(w, d) | (hi >> k);
|
||||
hi2 = (w - d) >> j;
|
||||
lo2 = lo - (d << k);
|
||||
hi = MUX(ctl, hi2, hi);
|
||||
lo = MUX(ctl, lo2, lo);
|
||||
q |= ctl << k;
|
||||
}
|
||||
cf = GE(lo, d) | hi;
|
||||
q |= cf;
|
||||
*r = MUX(cf, lo - d, lo);
|
||||
return q;
|
||||
}
|
||||
72
src/int/i32_encode.c
Normal file
72
src/int/i32_encode.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_encode(void *dst, size_t len, const uint32_t *x)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t k;
|
||||
|
||||
buf = dst;
|
||||
|
||||
/*
|
||||
* Compute the announced size of x in bytes; extra bytes are
|
||||
* filled with zeros.
|
||||
*/
|
||||
k = (x[0] + 7) >> 3;
|
||||
while (len > k) {
|
||||
*buf ++ = 0;
|
||||
len --;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we use k as index within x[]. That index starts at 1;
|
||||
* we initialize it to the topmost complete word, and process
|
||||
* any remaining incomplete word.
|
||||
*/
|
||||
k = (len + 3) >> 2;
|
||||
switch (len & 3) {
|
||||
case 3:
|
||||
*buf ++ = x[k] >> 16;
|
||||
/* fall through */
|
||||
case 2:
|
||||
*buf ++ = x[k] >> 8;
|
||||
/* fall through */
|
||||
case 1:
|
||||
*buf ++ = x[k];
|
||||
k --;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode all complete words.
|
||||
*/
|
||||
while (k > 0) {
|
||||
br_enc32be(buf, x[k]);
|
||||
k --;
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
60
src/int/i32_fmont.c
Normal file
60
src/int/i32_fmont.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i)
|
||||
{
|
||||
size_t len, u, v;
|
||||
|
||||
len = (m[0] + 31) >> 5;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t f;
|
||||
uint64_t cc;
|
||||
|
||||
f = x[1] * m0i;
|
||||
cc = 0;
|
||||
for (v = 0; v < len; v ++) {
|
||||
uint64_t z;
|
||||
|
||||
z = (uint64_t)x[v + 1] + MUL(f, m[v + 1]) + cc;
|
||||
cc = z >> 32;
|
||||
if (v != 0) {
|
||||
x[v] = (uint32_t)z;
|
||||
}
|
||||
}
|
||||
x[len] = (uint32_t)cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have to do an extra subtraction, but only if the
|
||||
* value in x[] is indeed greater than or equal to that of m[],
|
||||
* which is why we must do two calls (first call computes the
|
||||
* carry, second call performs the subtraction only if the carry
|
||||
* is 0).
|
||||
*/
|
||||
br_i32_sub(x, m, NOT(br_i32_sub(x, m, 0)));
|
||||
}
|
||||
39
src/int/i32_iszero.c
Normal file
39
src/int/i32_iszero.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i32_iszero(const uint32_t *x)
|
||||
{
|
||||
uint32_t z;
|
||||
size_t u;
|
||||
|
||||
z = 0;
|
||||
for (u = (x[0] + 31) >> 5; u > 0; u --) {
|
||||
z |= x[u];
|
||||
}
|
||||
return ~(z | -z) >> 31;
|
||||
}
|
||||
65
src/int/i32_modpow.c
Normal file
65
src/int/i32_modpow.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_modpow(uint32_t *x,
|
||||
const unsigned char *e, size_t elen,
|
||||
const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2)
|
||||
{
|
||||
size_t mlen;
|
||||
uint32_t k;
|
||||
|
||||
/*
|
||||
* 'mlen' is the length of m[] expressed in bytes (including
|
||||
* the "bit length" first field).
|
||||
*/
|
||||
mlen = ((m[0] + 63) >> 5) * sizeof m[0];
|
||||
|
||||
/*
|
||||
* Throughout the algorithm:
|
||||
* -- t1[] is in Montgomery representation; it contains x, x^2,
|
||||
* x^4, x^8...
|
||||
* -- The result is accumulated, in normal representation, in
|
||||
* the x[] array.
|
||||
* -- t2[] is used as destination buffer for each multiplication.
|
||||
*
|
||||
* Note that there is no need to call br_i32_from_monty().
|
||||
*/
|
||||
memcpy(t1, x, mlen);
|
||||
br_i32_to_monty(t1, m);
|
||||
br_i32_zero(x, m[0]);
|
||||
x[1] = 1;
|
||||
for (k = 0; k < ((uint32_t)elen << 3); k ++) {
|
||||
uint32_t ctl;
|
||||
|
||||
ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1;
|
||||
br_i32_montymul(t2, x, t1, m, m0i);
|
||||
CCOPY(ctl, x, t2, mlen);
|
||||
br_i32_montymul(t2, t1, t1, m, m0i);
|
||||
memcpy(t1, t2, mlen);
|
||||
}
|
||||
}
|
||||
69
src/int/i32_montmul.c
Normal file
69
src/int/i32_montmul.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
|
||||
const uint32_t *m, uint32_t m0i)
|
||||
{
|
||||
size_t len, u, v;
|
||||
uint64_t dh;
|
||||
|
||||
len = (m[0] + 31) >> 5;
|
||||
br_i32_zero(d, m[0]);
|
||||
dh = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
uint32_t f, xu;
|
||||
uint64_t r1, r2, zh;
|
||||
|
||||
xu = x[u + 1];
|
||||
f = (d[1] + x[u + 1] * y[1]) * m0i;
|
||||
r1 = 0;
|
||||
r2 = 0;
|
||||
for (v = 0; v < len; v ++) {
|
||||
uint64_t z;
|
||||
uint32_t t;
|
||||
|
||||
z = (uint64_t)d[v + 1] + MUL(xu, y[v + 1]) + r1;
|
||||
r1 = z >> 32;
|
||||
t = (uint32_t)z;
|
||||
z = (uint64_t)t + MUL(f, m[v + 1]) + r2;
|
||||
r2 = z >> 32;
|
||||
if (v != 0) {
|
||||
d[v] = (uint32_t)z;
|
||||
}
|
||||
}
|
||||
zh = dh + r1 + r2;
|
||||
d[len] = (uint32_t)zh;
|
||||
dh = zh >> 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* d[] may still be greater than m[] at that point; notably, the
|
||||
* 'dh' word may be non-zero.
|
||||
*/
|
||||
br_i32_sub(d, m, NEQ(dh, 0) | NOT(br_i32_sub(d, m, 0)));
|
||||
}
|
||||
52
src/int/i32_mulacc.c
Normal file
52
src/int/i32_mulacc.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
size_t alen, blen, u;
|
||||
|
||||
alen = (a[0] + 31) >> 5;
|
||||
blen = (b[0] + 31) >> 5;
|
||||
d[0] = a[0] + b[0];
|
||||
for (u = 0; u < blen; u ++) {
|
||||
uint32_t f;
|
||||
size_t v;
|
||||
uint64_t cc;
|
||||
|
||||
f = b[1 + u];
|
||||
cc = 0;
|
||||
for (v = 0; v < alen; v ++) {
|
||||
uint64_t z;
|
||||
|
||||
z = (uint64_t)d[1 + u + v] + MUL(f, a[1 + v]) + cc;
|
||||
cc = z >> 32;
|
||||
d[1 + u + v] = (uint32_t)z;
|
||||
}
|
||||
d[1 + u + alen] = (uint32_t)cc;
|
||||
}
|
||||
}
|
||||
138
src/int/i32_muladd.c
Normal file
138
src/int/i32_muladd.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m)
|
||||
{
|
||||
uint32_t m_bitlen;
|
||||
size_t u, mlen;
|
||||
uint32_t a0, a1, b0, hi, g, q, tb;
|
||||
uint32_t chf, clow, under, over;
|
||||
uint64_t cc;
|
||||
|
||||
/*
|
||||
* We can test on the modulus bit length since we accept to
|
||||
* leak that length.
|
||||
*/
|
||||
m_bitlen = m[0];
|
||||
if (m_bitlen == 0) {
|
||||
return;
|
||||
}
|
||||
if (m_bitlen <= 32) {
|
||||
x[1] = br_rem(x[1], z, m[1]);
|
||||
return;
|
||||
}
|
||||
mlen = (m_bitlen + 31) >> 5;
|
||||
|
||||
/*
|
||||
* Principle: we estimate the quotient (x*2^32+z)/m by
|
||||
* doing a 64/32 division with the high words.
|
||||
*
|
||||
* Let:
|
||||
* w = 2^32
|
||||
* a = (w*a0 + a1) * w^N + a2
|
||||
* b = b0 * w^N + b2
|
||||
* such that:
|
||||
* 0 <= a0 < w
|
||||
* 0 <= a1 < w
|
||||
* 0 <= a2 < w^N
|
||||
* w/2 <= b0 < w
|
||||
* 0 <= b2 < w^N
|
||||
* a < w*b
|
||||
* I.e. the two top words of a are a0:a1, the top word of b is
|
||||
* b0, we ensured that b0 is "full" (high bit set), and a is
|
||||
* such that the quotient q = a/b fits on one word (0 <= q < w).
|
||||
*
|
||||
* If a = b*q + r (with 0 <= r < q), we can estimate q by
|
||||
* doing an Euclidean division on the top words:
|
||||
* a0*w+a1 = b0*u + v (with 0 <= v < w)
|
||||
* Then the following holds:
|
||||
* 0 <= u <= w
|
||||
* u-2 <= q <= u
|
||||
*/
|
||||
a0 = br_i32_word(x, m_bitlen - 32);
|
||||
hi = x[mlen];
|
||||
memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
|
||||
x[1] = z;
|
||||
a1 = br_i32_word(x, m_bitlen - 32);
|
||||
b0 = br_i32_word(m, m_bitlen - 32);
|
||||
|
||||
/*
|
||||
* We estimate a divisor q. If the quotient returned by br_div()
|
||||
* is g:
|
||||
* -- If a0 == b0 then g == 0; we want q = 0xFFFFFFFF.
|
||||
* -- Otherwise:
|
||||
* -- if g == 0 then we set q = 0;
|
||||
* -- otherwise, we set q = g - 1.
|
||||
* The properties described above then ensure that the true
|
||||
* quotient is q-1, q or q+1.
|
||||
*/
|
||||
g = br_div(a0, a1, b0);
|
||||
q = MUX(EQ(a0, b0), 0xFFFFFFFF, MUX(EQ(g, 0), 0, g - 1));
|
||||
|
||||
/*
|
||||
* We subtract q*m from x (with the extra high word of value 'hi').
|
||||
* Since q may be off by 1 (in either direction), we may have to
|
||||
* add or subtract m afterwards.
|
||||
*
|
||||
* The 'tb' flag will be true (1) at the end of the loop if the
|
||||
* result is greater than or equal to the modulus (not counting
|
||||
* 'hi' or the carry).
|
||||
*/
|
||||
cc = 0;
|
||||
tb = 1;
|
||||
for (u = 1; u <= mlen; u ++) {
|
||||
uint32_t mw, zw, xw, nxw;
|
||||
uint64_t zl;
|
||||
|
||||
mw = m[u];
|
||||
zl = MUL(mw, q) + cc;
|
||||
cc = (uint32_t)(zl >> 32);
|
||||
zw = (uint32_t)zl;
|
||||
xw = x[u];
|
||||
nxw = xw - zw;
|
||||
cc += (uint64_t)GT(nxw, xw);
|
||||
x[u] = nxw;
|
||||
tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw));
|
||||
}
|
||||
|
||||
/*
|
||||
* If we underestimated q, then either cc < hi (one extra bit
|
||||
* beyond the top array word), or cc == hi and tb is true (no
|
||||
* extra bit, but the result is not lower than the modulus). In
|
||||
* these cases we must subtract m once.
|
||||
*
|
||||
* Otherwise, we may have overestimated, which will show as
|
||||
* cc > hi (thus a negative result). Correction is adding m once.
|
||||
*/
|
||||
chf = (uint32_t)(cc >> 32);
|
||||
clow = (uint32_t)cc;
|
||||
over = chf | GT(clow, hi);
|
||||
under = ~over & (tb | (~chf & LT(clow, hi)));
|
||||
br_i32_add(x, m, over);
|
||||
br_i32_sub(x, m, under);
|
||||
}
|
||||
39
src/int/i32_ninv32.c
Normal file
39
src/int/i32_ninv32.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i32_ninv32(uint32_t x)
|
||||
{
|
||||
uint32_t y;
|
||||
|
||||
y = 2 - x;
|
||||
y *= 2 - y * x;
|
||||
y *= 2 - y * x;
|
||||
y *= 2 - y * x;
|
||||
y *= 2 - y * x;
|
||||
return MUX(x & 1, -y, 0);
|
||||
}
|
||||
66
src/int/i32_reduce.c
Normal file
66
src/int/i32_reduce.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m)
|
||||
{
|
||||
uint32_t m_bitlen, a_bitlen;
|
||||
size_t mlen, alen, u;
|
||||
|
||||
m_bitlen = m[0];
|
||||
mlen = (m_bitlen + 31) >> 5;
|
||||
|
||||
x[0] = m_bitlen;
|
||||
if (m_bitlen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the source is shorter, then simply copy all words from a[]
|
||||
* and zero out the upper words.
|
||||
*/
|
||||
a_bitlen = a[0];
|
||||
alen = (a_bitlen + 31) >> 5;
|
||||
if (a_bitlen < m_bitlen) {
|
||||
memcpy(x + 1, a + 1, alen * sizeof *a);
|
||||
for (u = alen; u < mlen; u ++) {
|
||||
x[u + 1] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The source length is at least equal to that of the modulus.
|
||||
* We must thus copy N-1 words, and input the remaining words
|
||||
* one by one.
|
||||
*/
|
||||
memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a);
|
||||
x[mlen] = 0;
|
||||
for (u = 1 + alen - mlen; u > 0; u --) {
|
||||
br_i32_muladd_small(x, a[u], m);
|
||||
}
|
||||
}
|
||||
51
src/int/i32_sub.c
Normal file
51
src/int/i32_sub.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 63) >> 5;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw - bw - cc;
|
||||
|
||||
/*
|
||||
* Carry is 1 if naw > aw. Carry is 1 also if naw == aw
|
||||
* AND the carry was already 1.
|
||||
*/
|
||||
cc = (cc & EQ(naw, aw)) | GT(naw, aw);
|
||||
a[u] = MUX(ctl, naw, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
36
src/int/i32_tmont.c
Normal file
36
src/int/i32_tmont.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i32_to_monty(uint32_t *x, const uint32_t *m)
|
||||
{
|
||||
uint32_t k;
|
||||
|
||||
for (k = (m[0] + 31) >> 5; k > 0; k --) {
|
||||
br_i32_muladd_small(x, 0, m);
|
||||
}
|
||||
}
|
||||
122
src/mac/hmac.c
Normal file
122
src/mac/hmac.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static inline size_t
|
||||
block_size(const br_hash_class *dig)
|
||||
{
|
||||
unsigned ls;
|
||||
|
||||
ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF)
|
||||
& BR_HASHDESC_LBLEN_MASK;
|
||||
return (size_t)1 << ls;
|
||||
}
|
||||
|
||||
static void
|
||||
process_key(const br_hash_class **hc, void *ks,
|
||||
const void *key, size_t key_len, unsigned bb)
|
||||
{
|
||||
unsigned char tmp[256];
|
||||
size_t blen, u;
|
||||
|
||||
blen = block_size(*hc);
|
||||
memcpy(tmp, key, key_len);
|
||||
for (u = 0; u < key_len; u ++) {
|
||||
tmp[u] ^= (unsigned char)bb;
|
||||
}
|
||||
memset(tmp + key_len, bb, blen - key_len);
|
||||
(*hc)->init(hc);
|
||||
(*hc)->update(hc, tmp, blen);
|
||||
(*hc)->state(hc, ks);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_hmac_key_init(br_hmac_key_context *kc,
|
||||
const br_hash_class *dig, const void *key, size_t key_len)
|
||||
{
|
||||
br_hmac_allhash_context hc;
|
||||
unsigned char kbuf[64];
|
||||
|
||||
kc->dig_vtable = dig;
|
||||
hc.vtable = dig;
|
||||
if (key_len > block_size(dig)) {
|
||||
dig->init(&hc.vtable);
|
||||
dig->update(&hc.vtable, key, key_len);
|
||||
dig->out(&hc.vtable, kbuf);
|
||||
key = kbuf;
|
||||
key_len = br_digest_size(dig);
|
||||
}
|
||||
process_key(&hc.vtable, kc->ksi, key, key_len, 0x36);
|
||||
process_key(&hc.vtable, kc->kso, key, key_len, 0x5C);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_hmac_init(br_hmac_context *ctx,
|
||||
const br_hmac_key_context *kc, size_t out_len)
|
||||
{
|
||||
const br_hash_class *dig;
|
||||
size_t blen, hlen;
|
||||
|
||||
dig = kc->dig_vtable;
|
||||
blen = block_size(dig);
|
||||
dig->init(&ctx->dig.vtable);
|
||||
dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen);
|
||||
memcpy(ctx->kso, kc->kso, sizeof kc->kso);
|
||||
hlen = br_digest_size(dig);
|
||||
if (out_len > 0 && out_len < hlen) {
|
||||
hlen = out_len;
|
||||
}
|
||||
ctx->out_len = hlen;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_hmac_update(br_hmac_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
ctx->dig.vtable->update(&ctx->dig.vtable, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
size_t
|
||||
br_hmac_out(const br_hmac_context *ctx, void *out)
|
||||
{
|
||||
const br_hash_class *dig;
|
||||
br_hmac_allhash_context hc;
|
||||
unsigned char tmp[64];
|
||||
size_t blen, hlen;
|
||||
|
||||
dig = ctx->dig.vtable;
|
||||
dig->out(&ctx->dig.vtable, tmp);
|
||||
blen = block_size(dig);
|
||||
dig->init(&hc.vtable);
|
||||
dig->set_state(&hc.vtable, ctx->kso, (uint64_t)blen);
|
||||
hlen = br_digest_size(dig);
|
||||
dig->update(&hc.vtable, tmp, hlen);
|
||||
dig->out(&hc.vtable, tmp);
|
||||
memcpy(out, tmp, ctx->out_len);
|
||||
return ctx->out_len;
|
||||
}
|
||||
192
src/mac/hmac_ct.c
Normal file
192
src/mac/hmac_ct.c
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static inline size_t
|
||||
hash_size(const br_hash_class *dig)
|
||||
{
|
||||
return (unsigned)(dig->desc >> BR_HASHDESC_OUT_OFF)
|
||||
& BR_HASHDESC_OUT_MASK;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
block_size(const br_hash_class *dig)
|
||||
{
|
||||
unsigned ls;
|
||||
|
||||
ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF)
|
||||
& BR_HASHDESC_LBLEN_MASK;
|
||||
return (size_t)1 << ls;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
size_t
|
||||
br_hmac_outCT(const br_hmac_context *ctx,
|
||||
const void *data, size_t len, size_t min_len, size_t max_len,
|
||||
void *out)
|
||||
{
|
||||
/*
|
||||
* Method implemented here is inspired from the descriptions on:
|
||||
* https://www.imperialviolet.org/2013/02/04/luckythirteen.html
|
||||
*
|
||||
* Principle: we input bytes one by one. We use a MUX to push
|
||||
* padding bytes instead of data bytes when appropriate. At each
|
||||
* block limit, we get the current hash function state: this is
|
||||
* a potential output, since we handle MD padding ourselves.
|
||||
*
|
||||
* be 1 for big-endian, 0 for little-endian
|
||||
* po minimal MD padding length
|
||||
* bs block size (always a power of 2)
|
||||
* hlen hash output size
|
||||
*/
|
||||
|
||||
const br_hash_class *dig;
|
||||
br_hmac_allhash_context hc;
|
||||
int be;
|
||||
uint32_t po, bs;
|
||||
uint32_t kr, km, kl, kz, u;
|
||||
uint64_t count, ncount, bit_len;
|
||||
unsigned char tmp1[64], tmp2[64];
|
||||
size_t hlen;
|
||||
|
||||
/*
|
||||
* Copy the current hash context.
|
||||
*/
|
||||
hc = ctx->dig;
|
||||
|
||||
/*
|
||||
* Get function-specific information.
|
||||
*/
|
||||
dig = hc.vtable;
|
||||
be = (dig->desc & BR_HASHDESC_MD_PADDING_BE) != 0;
|
||||
po = 9;
|
||||
if (dig->desc & BR_HASHDESC_MD_PADDING_128) {
|
||||
po += 8;
|
||||
}
|
||||
bs = block_size(dig);
|
||||
hlen = hash_size(dig);
|
||||
|
||||
/*
|
||||
* Get current input length and compute total bit length.
|
||||
*/
|
||||
count = dig->state(&hc.vtable, tmp1);
|
||||
bit_len = (count + (uint64_t)len) << 3;
|
||||
|
||||
/*
|
||||
* We can input the blocks that we are sure we will use.
|
||||
* This offers better performance (no MUX for these blocks)
|
||||
* and also ensures that the remaining lengths fit on 32 bits.
|
||||
*/
|
||||
ncount = (count + (uint64_t)min_len) & ~(uint64_t)(bs - 1);
|
||||
if (ncount > count) {
|
||||
size_t zlen;
|
||||
|
||||
zlen = (size_t)(ncount - count);
|
||||
dig->update(&hc.vtable, data, zlen);
|
||||
data = (const unsigned char *)data + zlen;
|
||||
len -= zlen;
|
||||
max_len -= zlen;
|
||||
count = ncount;
|
||||
}
|
||||
|
||||
/*
|
||||
* At that point:
|
||||
* -- 'count' contains the number of bytes already processed
|
||||
* (in total).
|
||||
* -- We must input 'len' bytes. 'min_len' is unimportant: we
|
||||
* used it to know how many full blocks we could process
|
||||
* directly. Now only len and max_len matter.
|
||||
*
|
||||
* We compute kr, kl, kz and km.
|
||||
* kr number of input bytes already in the current block
|
||||
* km index of the first byte after the end of the last padding
|
||||
* block, if length is max_len
|
||||
* kz index of the last byte of the actual last padding block
|
||||
* kl index of the start of the encoded length
|
||||
*
|
||||
* km, kz and kl are counted from the current offset in the
|
||||
* input data.
|
||||
*/
|
||||
kr = (uint32_t)count & (bs - 1);
|
||||
kz = ((kr + (uint32_t)len + po + bs - 1) & ~(bs - 1)) - 1 - kr;
|
||||
kl = kz - 7;
|
||||
km = ((kr + (uint32_t)max_len + po + bs - 1) & ~(bs - 1)) - kr;
|
||||
|
||||
/*
|
||||
* We must now process km bytes. For index u from 0 to km-1:
|
||||
* d is from data[] if u < max_len, 0x00 otherwise
|
||||
* e is an encoded length byte or 0x00, depending on u
|
||||
* The tests for d and e need not be constant-time, since
|
||||
* they relate only to u and max_len, not to the actual length.
|
||||
*
|
||||
* Actual input length is then:
|
||||
* d if u < len
|
||||
* 0x80 if u == len
|
||||
* 0x00 if u > len and u < kl
|
||||
* e if u >= kl
|
||||
*
|
||||
* Hash state is obtained whenever we reach a full block. This
|
||||
* is the result we want if and only if u == kz.
|
||||
*/
|
||||
for (u = 0; u < km; u ++) {
|
||||
uint32_t v;
|
||||
uint32_t d, e, x0, x1;
|
||||
unsigned char x[1];
|
||||
|
||||
d = (u < max_len) ? ((const unsigned char *)data)[u] : 0x00;
|
||||
v = (kr + u) & (bs - 1);
|
||||
if (v >= (bs - 8)) {
|
||||
unsigned j;
|
||||
|
||||
j = (v - (bs - 8)) << 3;
|
||||
if (be) {
|
||||
e = (uint32_t)(bit_len >> (56 - j));
|
||||
} else {
|
||||
e = (uint32_t)(bit_len >> j);
|
||||
}
|
||||
e &= 0xFF;
|
||||
} else {
|
||||
e = 0x00;
|
||||
}
|
||||
x0 = MUX(EQ(u, (uint32_t)len), 0x80, d);
|
||||
x1 = MUX(LT(u, kl), 0x00, e);
|
||||
x[0] = MUX(LE(u, (uint32_t)len), x0, x1);
|
||||
dig->update(&hc.vtable, x, 1);
|
||||
if (v == (bs - 1)) {
|
||||
dig->state(&hc.vtable, tmp1);
|
||||
CCOPY(EQ(u, kz), tmp2, tmp1, hlen);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Inner hash output is in tmp2[]; we finish processing.
|
||||
*/
|
||||
dig->init(&hc.vtable);
|
||||
dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs);
|
||||
dig->update(&hc.vtable, tmp2, hlen);
|
||||
dig->out(&hc.vtable, tmp2);
|
||||
memcpy(out, tmp2, ctx->out_len);
|
||||
return ctx->out_len;
|
||||
}
|
||||
157
src/rand/hmac_drbg.c
Normal file
157
src/rand/hmac_drbg.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_hmac_drbg_init(br_hmac_drbg_context *ctx,
|
||||
const br_hash_class *digest_class, const void *seed, size_t len)
|
||||
{
|
||||
size_t hlen;
|
||||
|
||||
ctx->vtable = &br_hmac_drbg_vtable;
|
||||
hlen = br_digest_size(digest_class);
|
||||
memset(ctx->K, 0x00, hlen);
|
||||
memset(ctx->V, 0x01, hlen);
|
||||
ctx->digest_class = digest_class;
|
||||
br_hmac_drbg_update(ctx, seed, len);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len)
|
||||
{
|
||||
const br_hash_class *dig;
|
||||
br_hmac_key_context kc;
|
||||
br_hmac_context hc;
|
||||
size_t hlen;
|
||||
unsigned char *buf;
|
||||
unsigned char x;
|
||||
|
||||
dig = ctx->digest_class;
|
||||
hlen = br_digest_size(dig);
|
||||
br_hmac_key_init(&kc, dig, ctx->K, hlen);
|
||||
buf = out;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
br_hmac_out(&hc, ctx->V);
|
||||
clen = hlen;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(buf, ctx->V, clen);
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* To prepare the state for the next request, we should call
|
||||
* br_hmac_drbg_update() with an empty additional seed. However,
|
||||
* we already have an initialized HMAC context with the right
|
||||
* initial key, and we don't want to push another one on the
|
||||
* stack, so we inline that update() call here.
|
||||
*/
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
x = 0x00;
|
||||
br_hmac_update(&hc, &x, 1);
|
||||
br_hmac_out(&hc, ctx->K);
|
||||
br_hmac_key_init(&kc, dig, ctx->K, hlen);
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
br_hmac_out(&hc, ctx->V);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_hmac_drbg_update(br_hmac_drbg_context *ctx, const void *seed, size_t len)
|
||||
{
|
||||
const br_hash_class *dig;
|
||||
br_hmac_key_context kc;
|
||||
br_hmac_context hc;
|
||||
size_t hlen;
|
||||
unsigned char x;
|
||||
|
||||
dig = ctx->digest_class;
|
||||
hlen = br_digest_size(dig);
|
||||
|
||||
/*
|
||||
* 1. K = HMAC(K, V || 0x00 || seed)
|
||||
*/
|
||||
br_hmac_key_init(&kc, dig, ctx->K, hlen);
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
x = 0x00;
|
||||
br_hmac_update(&hc, &x, 1);
|
||||
br_hmac_update(&hc, seed, len);
|
||||
br_hmac_out(&hc, ctx->K);
|
||||
br_hmac_key_init(&kc, dig, ctx->K, hlen);
|
||||
|
||||
/*
|
||||
* 2. V = HMAC(K, V)
|
||||
*/
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
br_hmac_out(&hc, ctx->V);
|
||||
|
||||
/*
|
||||
* 3. If the additional seed is empty, then stop here.
|
||||
*/
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4. K = HMAC(K, V || 0x01 || seed)
|
||||
*/
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
x = 0x01;
|
||||
br_hmac_update(&hc, &x, 1);
|
||||
br_hmac_update(&hc, seed, len);
|
||||
br_hmac_out(&hc, ctx->K);
|
||||
br_hmac_key_init(&kc, dig, ctx->K, hlen);
|
||||
|
||||
/*
|
||||
* 5. V = HMAC(K, V)
|
||||
*/
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, ctx->V, hlen);
|
||||
br_hmac_out(&hc, ctx->V);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_prng_class br_hmac_drbg_vtable = {
|
||||
sizeof(br_hmac_drbg_context),
|
||||
(void (*)(const br_prng_class **, const void *, const void *, size_t))
|
||||
&br_hmac_drbg_init,
|
||||
(void (*)(const br_prng_class **, void *, size_t))
|
||||
&br_hmac_drbg_generate,
|
||||
(void (*)(const br_prng_class **, const void *, size_t))
|
||||
&br_hmac_drbg_update
|
||||
};
|
||||
104
src/rsa/rsa_i31_pkcs1_sign.c
Normal file
104
src/rsa/rsa_i31_pkcs1_sign.c
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const br_rsa_private_key *sk, unsigned char *x)
|
||||
{
|
||||
size_t u, x3, xlen;
|
||||
|
||||
/*
|
||||
* Padded hash value has format:
|
||||
* 00 01 FF .. FF 00 30 x1 30 x2 06 x3 OID 05 00 04 x4 HASH
|
||||
*
|
||||
* with the following rules:
|
||||
*
|
||||
* -- Total length is equal to the modulus length (unsigned
|
||||
* encoding).
|
||||
*
|
||||
* -- There must be at least eight bytes of value 0xFF.
|
||||
*
|
||||
* -- x4 is equal to the hash length (hash_len).
|
||||
*
|
||||
* -- x3 is equal to the encoded OID value length (hash_oid[0]).
|
||||
*
|
||||
* -- x2 = x3 + 4.
|
||||
*
|
||||
* -- x1 = x2 + x4 + 4 = x3 + x4 + 8.
|
||||
*
|
||||
* Note: the "05 00" is optional (signatures with and without
|
||||
* that sequence exist in practice), but notes in PKCS#1 seem to
|
||||
* indicate that the presence of that sequence (specifically,
|
||||
* an ASN.1 NULL value for the hash parameters) may be slightly
|
||||
* more "standard" than the opposite.
|
||||
*/
|
||||
xlen = (sk->n_bitlen + 7) >> 3;
|
||||
|
||||
if (hash_oid == NULL) {
|
||||
if (xlen < hash_len + 11) {
|
||||
return 0;
|
||||
}
|
||||
x[0] = 0x00;
|
||||
x[1] = 0x01;
|
||||
u = xlen - hash_len;
|
||||
memset(x + 2, 0xFF, u - 3);
|
||||
x[u - 1] = 0x00;
|
||||
} else {
|
||||
x3 = hash_oid[0];
|
||||
|
||||
/*
|
||||
* Check that there is enough room for all the elements,
|
||||
* including at least eight bytes of value 0xFF.
|
||||
*/
|
||||
if (xlen < (x3 + hash_len + 21)) {
|
||||
return 0;
|
||||
}
|
||||
x[0] = 0x00;
|
||||
x[1] = 0x01;
|
||||
u = xlen - x3 - hash_len - 11;
|
||||
memset(x + 2, 0xFF, u - 2);
|
||||
x[u] = 0x00;
|
||||
x[u + 1] = 0x30;
|
||||
x[u + 2] = x3 + hash_len + 8;
|
||||
x[u + 3] = 0x30;
|
||||
x[u + 4] = x3 + 4;
|
||||
x[u + 5] = 0x06;
|
||||
memcpy(x + u + 6, hash_oid, x3 + 1);
|
||||
u += x3 + 7;
|
||||
x[u ++] = 0x05;
|
||||
x[u ++] = 0x00;
|
||||
x[u ++] = 0x04;
|
||||
x[u ++] = hash_len;
|
||||
}
|
||||
memcpy(x + u, hash, hash_len);
|
||||
|
||||
/*
|
||||
* Do the actual computation.
|
||||
*/
|
||||
return br_rsa_i31_private(x, sk);
|
||||
}
|
||||
126
src/rsa/rsa_i31_pkcs1_vrfy.c
Normal file
126
src/rsa/rsa_i31_pkcs1_vrfy.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen,
|
||||
const unsigned char *hash_oid, size_t hash_len,
|
||||
const br_rsa_public_key *pk, unsigned char *hash_out)
|
||||
{
|
||||
static const unsigned char pad1[] = {
|
||||
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
unsigned char sig[BR_MAX_RSA_SIZE >> 3];
|
||||
unsigned char pad2[43];
|
||||
size_t u, x2, x3, pad_len, zlen;
|
||||
|
||||
if (xlen > (sizeof sig) || xlen < 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(sig, x, xlen);
|
||||
if (!br_rsa_i31_public(sig, xlen, pk)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expected format:
|
||||
* 00 01 FF ... FF 00 30 x1 30 x2 06 x3 OID [ 05 00 ] 04 x4 HASH
|
||||
*
|
||||
* with the following rules:
|
||||
*
|
||||
* -- Total length is that of the modulus and the signature
|
||||
* (this was already verified by br_rsa_i31_public()).
|
||||
*
|
||||
* -- There are at least eight bytes of value 0xFF.
|
||||
*
|
||||
* -- x4 is equal to the hash length (hash_len).
|
||||
*
|
||||
* -- x3 is equal to the encoded OID value length (so x3 is the
|
||||
* first byte of hash_oid[]).
|
||||
*
|
||||
* -- If the "05 00" is present, then x2 == x3 + 4; otherwise,
|
||||
* x2 == x3 + 2.
|
||||
*
|
||||
* -- x1 == x2 + x4 + 4.
|
||||
*
|
||||
* So the total length after the last "FF" is either x3 + x4 + 11
|
||||
* (with the "05 00") or x3 + x4 + 9 (without the "05 00").
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check the "00 01 FF .. FF 00" with at least eight 0xFF bytes.
|
||||
* The comparaison is valid because we made sure that the signature
|
||||
* is at least 11 bytes long.
|
||||
*/
|
||||
if (memcmp(sig, pad1, sizeof pad1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
for (u = sizeof pad1; u < xlen; u ++) {
|
||||
if (sig[u] != 0xFF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remaining length is xlen - u bytes (including the 00 just
|
||||
* after the last FF). This must be equal to one of the two
|
||||
* possible values (depending on whether the "05 00" sequence is
|
||||
* present or not).
|
||||
*/
|
||||
if (hash_oid == NULL) {
|
||||
if (xlen - u != hash_len + 1 || sig[u] != 0x00) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
x3 = hash_oid[0];
|
||||
pad_len = x3 + 9;
|
||||
memset(pad2, 0, pad_len);
|
||||
zlen = xlen - u - hash_len;
|
||||
if (zlen == pad_len) {
|
||||
x2 = x3 + 2;
|
||||
} else if (zlen == pad_len + 2) {
|
||||
x2 = x3 + 4;
|
||||
pad_len = zlen;
|
||||
pad2[pad_len - 4] = 0x05;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
pad2[1] = 0x30;
|
||||
pad2[2] = x2 + hash_len + 4;
|
||||
pad2[3] = 0x30;
|
||||
pad2[4] = x2;
|
||||
pad2[5] = 0x06;
|
||||
memcpy(pad2 + 6, hash_oid, x3 + 1);
|
||||
pad2[pad_len - 2] = 0x04;
|
||||
pad2[pad_len - 1] = hash_len;
|
||||
if (memcmp(pad2, sig + u, pad_len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy(hash_out, sig + xlen - hash_len, hash_len);
|
||||
return 1;
|
||||
}
|
||||
146
src/rsa/rsa_i31_priv.c
Normal file
146
src/rsa/rsa_i31_priv.c
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define U (1 + ((BR_MAX_RSA_FACTOR + 30) / 31))
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk)
|
||||
{
|
||||
const unsigned char *p, *q;
|
||||
size_t plen, qlen;
|
||||
uint32_t tmp[6 * U];
|
||||
uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
|
||||
uint32_t p0i, q0i;
|
||||
size_t xlen;
|
||||
|
||||
/*
|
||||
* All our temporary buffers are from the tmp[] array.
|
||||
*
|
||||
* The mp, mq, s1, s2, t1 and t2 buffers are large enough to
|
||||
* contain a RSA factor. The t3 buffer can contain a complete
|
||||
* RSA modulus. t3 shares its storage space with s2, s1 and t1,
|
||||
* in that order (this is important, see below).
|
||||
*/
|
||||
mq = tmp;
|
||||
mp = tmp + U;
|
||||
t2 = tmp + 2 * U;
|
||||
s2 = tmp + 3 * U;
|
||||
s1 = tmp + 4 * U;
|
||||
t1 = tmp + 5 * U;
|
||||
t3 = s2;
|
||||
|
||||
/*
|
||||
* Compute the actual lengths (in bytes) of p and q, and check
|
||||
* that they fit within our stack buffers.
|
||||
*/
|
||||
p = sk->p;
|
||||
plen = sk->plen;
|
||||
while (plen > 0 && *p == 0) {
|
||||
p ++;
|
||||
plen --;
|
||||
}
|
||||
q = sk->q;
|
||||
qlen = sk->qlen;
|
||||
while (qlen > 0 && *q == 0) {
|
||||
q ++;
|
||||
qlen --;
|
||||
}
|
||||
if (plen > (BR_MAX_RSA_FACTOR >> 3)
|
||||
|| qlen > (BR_MAX_RSA_FACTOR >> 3))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode p and q.
|
||||
*/
|
||||
br_i31_decode(mp, p, plen);
|
||||
br_i31_decode(mq, q, qlen);
|
||||
|
||||
/*
|
||||
* Compute signature length (in bytes).
|
||||
*/
|
||||
xlen = (sk->n_bitlen + 7) >> 3;
|
||||
|
||||
/*
|
||||
* Compute s1 = x^dp mod p.
|
||||
*/
|
||||
p0i = br_i31_ninv31(mp[1]);
|
||||
br_i31_decode_reduce(s1, x, xlen, mp);
|
||||
br_i31_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s2 = x^dq mod q.
|
||||
*/
|
||||
q0i = br_i31_ninv31(mq[1]);
|
||||
br_i31_decode_reduce(s2, x, xlen, mq);
|
||||
br_i31_modpow(s2, sk->dq, sk->dqlen, mq, q0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute:
|
||||
* h = (s1 - s2)*(1/q) mod p
|
||||
* s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
|
||||
* unclear about whether p may be lower than q (some existing,
|
||||
* widely deployed implementations of RSA don't tolerate p < q),
|
||||
* but we want to support that occurrence, so we need to use the
|
||||
* reduction function.
|
||||
*
|
||||
* Since we use br_i31_decode_reduce() for iq (purportedly, the
|
||||
* inverse of q modulo p), we also tolerate improperly large
|
||||
* values for this parameter.
|
||||
*/
|
||||
br_i31_reduce(t2, s2, mp);
|
||||
br_i31_add(s1, mp, br_i31_sub(s1, t2, 1));
|
||||
br_i31_to_monty(s1, mp);
|
||||
br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp);
|
||||
br_i31_montymul(t2, s1, t1, mp, p0i);
|
||||
|
||||
/*
|
||||
* h is now in t2. We compute the final result:
|
||||
* s = s2 + q*h
|
||||
* All these operations are non-modular.
|
||||
*
|
||||
* We need mq, s2 and t2. We use the t3 buffer as destination.
|
||||
* The buffers mp, s1 and t1 are no longer needed. Moreover,
|
||||
* the first step is to copy s2 into the destination buffer t3.
|
||||
* We thus arranged for t3 to actually share space with s2, and
|
||||
* to be followed by the space formerly used by s1 and t1.
|
||||
*/
|
||||
br_i31_mulacc(t3, mq, t2);
|
||||
|
||||
/*
|
||||
* Encode the result. Since we already checked the value of xlen,
|
||||
* we can just use it right away.
|
||||
*/
|
||||
br_i31_encode(x, xlen, t3);
|
||||
|
||||
/*
|
||||
* The only error conditions remaining at that point are invalid
|
||||
* values for p and q (even integers).
|
||||
*/
|
||||
return p0i & q0i & 1;
|
||||
}
|
||||
77
src/rsa/rsa_i31_pub.c
Normal file
77
src/rsa/rsa_i31_pub.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i31_public(unsigned char *x, size_t xlen,
|
||||
const br_rsa_public_key *pk)
|
||||
{
|
||||
const unsigned char *n;
|
||||
size_t nlen;
|
||||
uint32_t m[1 + ((BR_MAX_RSA_SIZE + 30) / 31)];
|
||||
uint32_t a[1 + ((BR_MAX_RSA_SIZE + 30) / 31)];
|
||||
uint32_t t1[1 + ((BR_MAX_RSA_SIZE + 30) / 31)];
|
||||
uint32_t t2[1 + ((BR_MAX_RSA_SIZE + 30) / 31)];
|
||||
uint32_t m0i, r;
|
||||
|
||||
/*
|
||||
* Get the actual length of the modulus, and see if it fits within
|
||||
* our stack buffer. We also check that the length of x[] is valid.
|
||||
*/
|
||||
n = pk->n;
|
||||
nlen = pk->nlen;
|
||||
while (nlen > 0 && *n == 0) {
|
||||
n ++;
|
||||
nlen --;
|
||||
}
|
||||
if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
|
||||
return 0;
|
||||
}
|
||||
br_i31_decode(m, n, nlen);
|
||||
m0i = br_i31_ninv31(m[1]);
|
||||
|
||||
/*
|
||||
* Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
|
||||
* an odd integer.
|
||||
*/
|
||||
r = m0i & 1;
|
||||
|
||||
/*
|
||||
* Decode x[] into a[]; we also check that its value is proper.
|
||||
*/
|
||||
r &= br_i31_decode_mod(a, x, xlen, m);
|
||||
|
||||
/*
|
||||
* Compute the modular exponentiation.
|
||||
*/
|
||||
br_i31_modpow(a, pk->e, pk->elen, m, m0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Encode the result.
|
||||
*/
|
||||
br_i31_encode(x, xlen, a);
|
||||
return r;
|
||||
}
|
||||
102
src/rsa/rsa_i32_pkcs1_sign.c
Normal file
102
src/rsa/rsa_i32_pkcs1_sign.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const br_rsa_private_key *sk, unsigned char *x)
|
||||
{
|
||||
size_t u, x3, xlen;
|
||||
|
||||
/*
|
||||
* Padded hash value has format:
|
||||
* 00 01 FF .. FF 00 30 x1 30 x2 06 x3 OID 05 00 04 x4 HASH
|
||||
*
|
||||
* with the following rules:
|
||||
*
|
||||
* -- Total length is equal to the modulus length (unsigned
|
||||
* encoding).
|
||||
*
|
||||
* -- There must be at least eight bytes of value 0xFF.
|
||||
*
|
||||
* -- x4 is equal to the hash length (hash_len).
|
||||
*
|
||||
* -- x3 is equal to the encoded OID value length (hash_oid[0]).
|
||||
*
|
||||
* -- x2 = x3 + 4.
|
||||
*
|
||||
* -- x1 = x2 + x4 + 4 = x3 + x4 + 8.
|
||||
*
|
||||
* Note: the "05 00" is optional (signatures with and without
|
||||
* that sequence exist in practice), but notes in PKCS#1 seem to
|
||||
* indicate that the presence of that sequence (specifically,
|
||||
* an ASN.1 NULL value for the hash parameters) may be slightly
|
||||
* more "standard" than the opposite.
|
||||
*/
|
||||
xlen = (sk->n_bitlen + 7) >> 3;
|
||||
|
||||
if (hash_oid == NULL) {
|
||||
if (xlen < hash_len + 11) {
|
||||
return 0;
|
||||
}
|
||||
u = xlen - hash_len;
|
||||
memset(x + 2, 0xFF, u - 3);
|
||||
x[u - 1] = 0x00;
|
||||
} else {
|
||||
x3 = hash_oid[0];
|
||||
|
||||
/*
|
||||
* Check that there is enough room for all the elements,
|
||||
* including at least eight bytes of value 0xFF.
|
||||
*/
|
||||
if (xlen < (x3 + hash_len + 21)) {
|
||||
return 0;
|
||||
}
|
||||
x[0] = 0x00;
|
||||
x[1] = 0x01;
|
||||
u = xlen - x3 - hash_len - 11;
|
||||
memset(x + 2, 0xFF, u - 2);
|
||||
x[u] = 0x00;
|
||||
x[u + 1] = 0x30;
|
||||
x[u + 2] = x3 + hash_len + 8;
|
||||
x[u + 3] = 0x30;
|
||||
x[u + 4] = x3 + 4;
|
||||
x[u + 5] = 0x06;
|
||||
memcpy(x + u + 6, hash_oid, x3 + 1);
|
||||
u += x3 + 7;
|
||||
x[u ++] = 0x05;
|
||||
x[u ++] = 0x00;
|
||||
x[u ++] = 0x04;
|
||||
x[u ++] = hash_len;
|
||||
}
|
||||
memcpy(x + u + 4, hash, hash_len);
|
||||
|
||||
/*
|
||||
* Do the actual computation.
|
||||
*/
|
||||
return br_rsa_i32_private(x, sk);
|
||||
}
|
||||
126
src/rsa/rsa_i32_pkcs1_vrfy.c
Normal file
126
src/rsa/rsa_i32_pkcs1_vrfy.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen,
|
||||
const unsigned char *hash_oid, size_t hash_len,
|
||||
const br_rsa_public_key *pk, unsigned char *hash_out)
|
||||
{
|
||||
static const unsigned char pad1[] = {
|
||||
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
unsigned char sig[BR_MAX_RSA_SIZE >> 3];
|
||||
unsigned char pad2[43];
|
||||
size_t u, x2, x3, pad_len, zlen;
|
||||
|
||||
if (xlen > (sizeof sig) || xlen < 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(sig, x, xlen);
|
||||
if (!br_rsa_i32_public(sig, xlen, pk)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expected format:
|
||||
* 00 01 FF ... FF 00 30 x1 30 x2 06 x3 OID [ 05 00 ] 04 x4 HASH
|
||||
*
|
||||
* with the following rules:
|
||||
*
|
||||
* -- Total length is that of the modulus and the signature
|
||||
* (this was already verified by br_rsa_i32_public()).
|
||||
*
|
||||
* -- There are at least eight bytes of value 0xFF.
|
||||
*
|
||||
* -- x4 is equal to the hash length (hash_len).
|
||||
*
|
||||
* -- x3 is equal to the encoded OID value length (so x3 is the
|
||||
* first byte of hash_oid[]).
|
||||
*
|
||||
* -- If the "05 00" is present, then x2 == x3 + 4; otherwise,
|
||||
* x2 == x3 + 2.
|
||||
*
|
||||
* -- x1 == x2 + x4 + 4.
|
||||
*
|
||||
* So the total length after the last "FF" is either x3 + x4 + 11
|
||||
* (with the "05 00") or x3 + x4 + 9 (without the "05 00").
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check the "00 01 FF .. FF 00" with at least eight 0xFF bytes.
|
||||
* The comparaison is valid because we made sure that the signature
|
||||
* is at least 11 bytes long.
|
||||
*/
|
||||
if (memcmp(sig, pad1, sizeof pad1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
for (u = sizeof pad1; u < xlen; u ++) {
|
||||
if (sig[u] != 0xFF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remaining length is xlen - u bytes (including the 00 just
|
||||
* after the last FF). This must be equal to one of the two
|
||||
* possible values (depending on whether the "05 00" sequence is
|
||||
* present or not).
|
||||
*/
|
||||
if (hash_oid == NULL) {
|
||||
if (xlen - u != hash_len + 1 || sig[u] != 0x00) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
x3 = hash_oid[0];
|
||||
pad_len = x3 + 9;
|
||||
memset(pad2, 0, pad_len);
|
||||
zlen = xlen - u - hash_len;
|
||||
if (zlen == pad_len) {
|
||||
x2 = x3 + 2;
|
||||
} else if (zlen == pad_len + 2) {
|
||||
x2 = x3 + 4;
|
||||
pad_len = zlen;
|
||||
pad2[pad_len - 4] = 0x05;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
pad2[1] = 0x30;
|
||||
pad2[2] = x2 + hash_len + 4;
|
||||
pad2[3] = 0x30;
|
||||
pad2[4] = x2;
|
||||
pad2[5] = 0x06;
|
||||
memcpy(pad2 + 6, hash_oid, x3 + 1);
|
||||
pad2[pad_len - 2] = 0x04;
|
||||
pad2[pad_len - 1] = hash_len;
|
||||
if (memcmp(pad2, sig + u, pad_len) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy(hash_out, sig + xlen - hash_len, hash_len);
|
||||
return 1;
|
||||
}
|
||||
153
src/rsa/rsa_i32_priv.c
Normal file
153
src/rsa/rsa_i32_priv.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define U (1 + (BR_MAX_RSA_FACTOR >> 5))
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk)
|
||||
{
|
||||
const unsigned char *p, *q;
|
||||
size_t plen, qlen;
|
||||
uint32_t tmp[6 * U];
|
||||
uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
|
||||
uint32_t p0i, q0i;
|
||||
size_t xlen;
|
||||
|
||||
/*
|
||||
* All our temporary buffers are from the tmp[] array.
|
||||
*
|
||||
* The mp, mq, s1, s2, t1 and t2 buffers are large enough to
|
||||
* contain a RSA factor. The t3 buffer can contain a complete
|
||||
* RSA modulus. t3 shares its storage space with s2, s1 and t1,
|
||||
* in that order (this is important, see below).
|
||||
*/
|
||||
mq = tmp;
|
||||
mp = tmp + U;
|
||||
t2 = tmp + 2 * U;
|
||||
s2 = tmp + 3 * U;
|
||||
s1 = tmp + 4 * U;
|
||||
t1 = tmp + 5 * U;
|
||||
t3 = s2;
|
||||
|
||||
/*
|
||||
* Compute the actual lengths (in bytes) of p and q, and check
|
||||
* that they fit within our stack buffers.
|
||||
*/
|
||||
p = sk->p;
|
||||
plen = sk->plen;
|
||||
while (plen > 0 && *p == 0) {
|
||||
p ++;
|
||||
plen --;
|
||||
}
|
||||
q = sk->q;
|
||||
qlen = sk->qlen;
|
||||
while (qlen > 0 && *q == 0) {
|
||||
q ++;
|
||||
qlen --;
|
||||
}
|
||||
if (plen > (BR_MAX_RSA_FACTOR >> 3)
|
||||
|| qlen > (BR_MAX_RSA_FACTOR >> 3))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode p and q.
|
||||
*/
|
||||
br_i32_decode(mp, p, plen);
|
||||
br_i32_decode(mq, q, qlen);
|
||||
|
||||
/*
|
||||
* obsolete -- we do not compute the length of n, it is now
|
||||
* an input parameter.
|
||||
br_i32_zero(t3, mp[0]);
|
||||
br_i32_mulacc(t3, mp, mq);
|
||||
n_bitlen = br_i32_bit_length(t3 + 1, (t3[0] + 31) >> 5);
|
||||
if (xlen != ((n_bitlen + 7) >> 3)) {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
xlen = (sk->n_bitlen + 7) >> 3;
|
||||
|
||||
/*
|
||||
* Compute s1 = x^dp mod p.
|
||||
*/
|
||||
p0i = br_i32_ninv32(mp[1]);
|
||||
br_i32_decode_reduce(s1, x, xlen, mp);
|
||||
br_i32_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s2 = x^dq mod q.
|
||||
*/
|
||||
q0i = br_i32_ninv32(mq[1]);
|
||||
br_i32_decode_reduce(s2, x, xlen, mq);
|
||||
br_i32_modpow(s2, sk->dq, sk->dqlen, mq, q0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute:
|
||||
* h = (s1 - s2)*(1/q) mod p
|
||||
* s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
|
||||
* unclear about whether p may be lower than q (some existing,
|
||||
* widely deployed implementations of RSA don't tolerate p < q),
|
||||
* but we want to support that occurrence, so we need to use the
|
||||
* reduction function.
|
||||
*
|
||||
* Since we use br_i32_decode_reduce() for iq (purportedly, the
|
||||
* inverse of q modulo p), we also tolerate improperly large
|
||||
* values for this parameter.
|
||||
*/
|
||||
br_i32_reduce(t2, s2, mp);
|
||||
br_i32_add(s1, mp, br_i32_sub(s1, t2, 1));
|
||||
br_i32_to_monty(s1, mp);
|
||||
br_i32_decode_reduce(t1, sk->iq, sk->iqlen, mp);
|
||||
br_i32_montymul(t2, s1, t1, mp, p0i);
|
||||
|
||||
/*
|
||||
* h is now in t2. We compute the final result:
|
||||
* s = s2 + q*h
|
||||
* All these operations are non-modular.
|
||||
*
|
||||
* We need mq, s2 and t2. We use the t3 buffer as destination.
|
||||
* The buffers mp, s1 and t1 are no longer needed. Moreover,
|
||||
* the first step is to copy s2 into the destination buffer t3.
|
||||
* We thus arranged for t3 to actually share space with s2, and
|
||||
* to be followed by the space formerly used by s1 and t1.
|
||||
*/
|
||||
br_i32_mulacc(t3, mq, t2);
|
||||
|
||||
/*
|
||||
* Encode the result. Since we already checked the value of xlen,
|
||||
* we can just use it right away.
|
||||
*/
|
||||
br_i32_encode(x, xlen, t3);
|
||||
|
||||
/*
|
||||
* The only error conditions remaining at that point are invalid
|
||||
* values for p and q (even integers).
|
||||
*/
|
||||
return p0i & q0i & 1;
|
||||
}
|
||||
77
src/rsa/rsa_i32_pub.c
Normal file
77
src/rsa/rsa_i32_pub.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_i32_public(unsigned char *x, size_t xlen,
|
||||
const br_rsa_public_key *pk)
|
||||
{
|
||||
const unsigned char *n;
|
||||
size_t nlen;
|
||||
uint32_t m[1 + (BR_MAX_RSA_SIZE >> 5)];
|
||||
uint32_t a[1 + (BR_MAX_RSA_SIZE >> 5)];
|
||||
uint32_t t1[1 + (BR_MAX_RSA_SIZE >> 5)];
|
||||
uint32_t t2[1 + (BR_MAX_RSA_SIZE >> 5)];
|
||||
uint32_t m0i, r;
|
||||
|
||||
/*
|
||||
* Get the actual length of the modulus, and see if it fits within
|
||||
* our stack buffer. We also check that the length of x[] is valid.
|
||||
*/
|
||||
n = pk->n;
|
||||
nlen = pk->nlen;
|
||||
while (nlen > 0 && *n == 0) {
|
||||
n ++;
|
||||
nlen --;
|
||||
}
|
||||
if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
|
||||
return 0;
|
||||
}
|
||||
br_i32_decode(m, n, nlen);
|
||||
m0i = br_i32_ninv32(m[1]);
|
||||
|
||||
/*
|
||||
* Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
|
||||
* an odd integer.
|
||||
*/
|
||||
r = m0i & 1;
|
||||
|
||||
/*
|
||||
* Decode x[] into a[]; we also check that its value is proper.
|
||||
*/
|
||||
r &= br_i32_decode_mod(a, x, xlen, m);
|
||||
|
||||
/*
|
||||
* Compute the modular exponentiation.
|
||||
*/
|
||||
br_i32_modpow(a, pk->e, pk->elen, m, m0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Encode the result.
|
||||
*/
|
||||
br_i32_encode(x, xlen, a);
|
||||
return r;
|
||||
}
|
||||
52
src/rsa/rsa_ssl_decrypt.c
Normal file
52
src/rsa/rsa_ssl_decrypt.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_rsa.h */
|
||||
uint32_t
|
||||
br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
|
||||
unsigned char *data, size_t len)
|
||||
{
|
||||
uint32_t x;
|
||||
size_t u;
|
||||
|
||||
/*
|
||||
* A first check on length. Since this test works only on the
|
||||
* buffer length, it needs not (and cannot) be constant-time.
|
||||
*/
|
||||
if (len < 59 || len != (sk->n_bitlen + 7) >> 3) {
|
||||
return 0;
|
||||
}
|
||||
x = core(data, sk);
|
||||
|
||||
x &= EQ(data[0], 0x00);
|
||||
x &= EQ(data[1], 0x02);
|
||||
for (u = 2; u < (len - 49); u ++) {
|
||||
x &= NEQ(data[u], 0);
|
||||
}
|
||||
x &= EQ(data[len - 49], 0x00);
|
||||
memmove(data, data + len - 48, 48);
|
||||
return x;
|
||||
}
|
||||
71
src/ssl/prf.c
Normal file
71
src/ssl/prf.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_tls_phash(void *dst, size_t len,
|
||||
const br_hash_class *dig,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char tmp[64], a[64];
|
||||
br_hmac_key_context kc;
|
||||
br_hmac_context hc;
|
||||
size_t label_len, hlen;
|
||||
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
buf = dst;
|
||||
for (label_len = 0; label[label_len]; label_len ++);
|
||||
hlen = br_digest_size(dig);
|
||||
br_hmac_key_init(&kc, dig, secret, secret_len);
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, label, label_len);
|
||||
br_hmac_update(&hc, seed, seed_len);
|
||||
br_hmac_out(&hc, a);
|
||||
for (;;) {
|
||||
size_t u;
|
||||
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, a, hlen);
|
||||
br_hmac_update(&hc, label, label_len);
|
||||
br_hmac_update(&hc, seed, seed_len);
|
||||
br_hmac_out(&hc, tmp);
|
||||
for (u = 0; u < hlen && u < len; u ++) {
|
||||
buf[u] ^= tmp[u];
|
||||
}
|
||||
buf += u;
|
||||
len -= u;
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
br_hmac_init(&hc, &kc, 0);
|
||||
br_hmac_update(&hc, a, hlen);
|
||||
br_hmac_out(&hc, a);
|
||||
}
|
||||
}
|
||||
43
src/ssl/prf_md5sha1.c
Normal file
43
src/ssl/prf_md5sha1.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_tls10_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len)
|
||||
{
|
||||
const unsigned char *s1;
|
||||
size_t slen;
|
||||
|
||||
s1 = secret;
|
||||
slen = (secret_len + 1) >> 1;
|
||||
memset(dst, 0, len);
|
||||
br_tls_phash(dst, len, &br_md5_vtable,
|
||||
s1, slen, label, seed, seed_len);
|
||||
br_tls_phash(dst, len, &br_sha1_vtable,
|
||||
s1 + secret_len - slen, slen, label, seed, seed_len);
|
||||
}
|
||||
36
src/ssl/prf_sha256.c
Normal file
36
src/ssl/prf_sha256.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_tls12_sha256_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len)
|
||||
{
|
||||
memset(dst, 0, len);
|
||||
br_tls_phash(dst, len, &br_sha256_vtable,
|
||||
secret, secret_len, label, seed, seed_len);
|
||||
}
|
||||
36
src/ssl/prf_sha384.c
Normal file
36
src/ssl/prf_sha384.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_tls12_sha384_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len)
|
||||
{
|
||||
memset(dst, 0, len);
|
||||
br_tls_phash(dst, len, &br_sha384_vtable,
|
||||
secret, secret_len, label, seed, seed_len);
|
||||
}
|
||||
78
src/ssl/ssl_client.c
Normal file
78
src/ssl/ssl_client.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ssl.h */
|
||||
void
|
||||
br_ssl_client_zero(br_ssl_client_context *cc)
|
||||
{
|
||||
/*
|
||||
* For really standard C, we should explicitly set to NULL all
|
||||
* pointers, and 0 all other fields. However, on all our target
|
||||
* architectures, a direct memset() will work, be faster, and
|
||||
* use a lot less code.
|
||||
*/
|
||||
memset(cc, 0, sizeof *cc);
|
||||
}
|
||||
|
||||
/* see bearssl_ssl.h */
|
||||
int
|
||||
br_ssl_client_reset(br_ssl_client_context *cc,
|
||||
const char *server_name, int resume_session)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0);
|
||||
cc->eng.version_out = cc->eng.version_min;
|
||||
if (!resume_session) {
|
||||
br_ssl_client_forget_session(cc);
|
||||
}
|
||||
if (!br_ssl_engine_init_rand(&cc->eng)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We always set back the "reneg" flag to 0 because we use it
|
||||
* to distinguish between first handshake and renegotiation.
|
||||
* Note that "renegotiation" and "session resumption" are two
|
||||
* different things.
|
||||
*/
|
||||
cc->eng.reneg = 0;
|
||||
|
||||
if (server_name == NULL) {
|
||||
cc->eng.server_name[0] = 0;
|
||||
} else {
|
||||
n = strlen(server_name) + 1;
|
||||
if (n > sizeof cc->eng.server_name) {
|
||||
br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM);
|
||||
return 0;
|
||||
}
|
||||
memcpy(cc->eng.server_name, server_name, n);
|
||||
}
|
||||
|
||||
br_ssl_engine_hs_reset(&cc->eng,
|
||||
br_ssl_hs_client_init_main, br_ssl_hs_client_run);
|
||||
return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK;
|
||||
}
|
||||
194
src/ssl/ssl_client_full.c
Normal file
194
src/ssl/ssl_client_full.c
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ssl.h */
|
||||
void
|
||||
br_ssl_client_init_full(br_ssl_client_context *cc,
|
||||
br_x509_minimal_context *xc,
|
||||
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
|
||||
{
|
||||
/*
|
||||
* The "full" profile supports all implemented cipher suites.
|
||||
*
|
||||
* Rationale for suite order, from most important to least
|
||||
* important rule:
|
||||
*
|
||||
* -- Don't use 3DES if AES is available.
|
||||
* -- Try to have Forward Secrecy (ECDHE suite) if possible.
|
||||
* -- When not using Forward Secrecy, ECDH key exchange is
|
||||
* better than RSA key exchange (slightly more expensive on the
|
||||
* client, but much cheaper on the server, and it implies smaller
|
||||
* messages).
|
||||
* -- GCM is better than CBC.
|
||||
* -- AES-128 is preferred over AES-256 (AES-128 is already
|
||||
* strong enough, and AES-256 is 40% more expensive).
|
||||
*/
|
||||
static const uint16_t suites[] = {
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
};
|
||||
|
||||
/*
|
||||
* All hash functions are activated.
|
||||
* Note: the X.509 validation engine will nonetheless refuse to
|
||||
* validate signatures that use MD5 as hash function.
|
||||
*/
|
||||
static const br_hash_class *hashes[] = {
|
||||
&br_md5_vtable,
|
||||
&br_sha1_vtable,
|
||||
&br_sha224_vtable,
|
||||
&br_sha256_vtable,
|
||||
&br_sha384_vtable,
|
||||
&br_sha512_vtable
|
||||
};
|
||||
|
||||
int id;
|
||||
|
||||
/*
|
||||
* Reset client context and set supported versions from TLS-1.0
|
||||
* to TLS-1.2 (inclusive).
|
||||
*/
|
||||
br_ssl_client_zero(cc);
|
||||
br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
|
||||
|
||||
/*
|
||||
* X.509 engine uses SHA-256 to hash certificate DN (for
|
||||
* comparisons).
|
||||
*/
|
||||
br_x509_minimal_init(xc, &br_sha256_vtable,
|
||||
trust_anchors, trust_anchors_num);
|
||||
|
||||
/*
|
||||
* Set suites and asymmetric crypto implementations. We use the
|
||||
* "i31" code for RSA (it is somewhat faster than the "i32"
|
||||
* implementation).
|
||||
* TODO: change that when better implementations are made available.
|
||||
*/
|
||||
br_ssl_engine_set_suites(&cc->eng, suites,
|
||||
(sizeof suites) / (sizeof suites[0]));
|
||||
br_ssl_client_set_rsapub(cc, &br_rsa_i31_public);
|
||||
br_ssl_client_set_rsavrfy(cc, &br_rsa_i31_pkcs1_vrfy);
|
||||
br_ssl_engine_set_ec(&cc->eng, &br_ec_prime_i31);
|
||||
br_ssl_client_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1);
|
||||
br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
|
||||
br_x509_minimal_set_ecdsa(xc,
|
||||
&br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
|
||||
|
||||
/*
|
||||
* Set supported hash functions, for the SSL engine and for the
|
||||
* X.509 engine.
|
||||
*/
|
||||
for (id = br_md5_ID; id <= br_sha512_ID; id ++) {
|
||||
const br_hash_class *hc;
|
||||
|
||||
hc = hashes[id - 1];
|
||||
br_ssl_engine_set_hash(&cc->eng, id, hc);
|
||||
br_x509_minimal_set_hash(xc, id, hc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Link the X.509 engine in the SSL engine.
|
||||
*/
|
||||
br_ssl_engine_set_x509(&cc->eng, &xc->vtable);
|
||||
|
||||
/*
|
||||
* Set the PRF implementations.
|
||||
*/
|
||||
br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf);
|
||||
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
|
||||
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
|
||||
|
||||
/*
|
||||
* Symmetric encryption. We use the "constant-time"
|
||||
* implementations, which are the safest.
|
||||
*
|
||||
* On architectures detected as "64-bit", use the 64-bit
|
||||
* versions (aes_ct64, ghash_ctmul64).
|
||||
*/
|
||||
#if BR_64
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct64_cbcenc_vtable,
|
||||
&br_aes_ct64_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct64_ctr_vtable);
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul64);
|
||||
#else
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct_cbcenc_vtable,
|
||||
&br_aes_ct_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct_ctr_vtable);
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul);
|
||||
#endif
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_ct_cbcenc_vtable,
|
||||
&br_des_ct_cbcdec_vtable);
|
||||
|
||||
/*
|
||||
* Set the SSL record engines (CBC, GCM).
|
||||
*/
|
||||
br_ssl_engine_set_cbc(&cc->eng,
|
||||
&br_sslrec_in_cbc_vtable,
|
||||
&br_sslrec_out_cbc_vtable);
|
||||
br_ssl_engine_set_gcm(&cc->eng,
|
||||
&br_sslrec_in_gcm_vtable,
|
||||
&br_sslrec_out_gcm_vtable);
|
||||
}
|
||||
1468
src/ssl/ssl_engine.c
Normal file
1468
src/ssl/ssl_engine.c
Normal file
File diff suppressed because it is too large
Load diff
46
src/ssl/ssl_hashes.c
Normal file
46
src/ssl/ssl_hashes.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
int
|
||||
br_ssl_choose_hash(unsigned bf)
|
||||
{
|
||||
static const unsigned char pref[] = {
|
||||
br_sha256_ID, br_sha384_ID, br_sha512_ID,
|
||||
br_sha224_ID, br_sha1_ID
|
||||
};
|
||||
size_t u;
|
||||
|
||||
for (u = 0; u < sizeof pref; u ++) {
|
||||
int x;
|
||||
|
||||
x = pref[u];
|
||||
if ((bf >> x) & 1) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
1473
src/ssl/ssl_hs_client.c
Normal file
1473
src/ssl/ssl_hs_client.c
Normal file
File diff suppressed because it is too large
Load diff
992
src/ssl/ssl_hs_client.t0
Normal file
992
src/ssl/ssl_hs_client.t0
Normal file
|
|
@ -0,0 +1,992 @@
|
|||
\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
\
|
||||
\ Permission is hereby granted, free of charge, to any person obtaining
|
||||
\ a copy of this software and associated documentation files (the
|
||||
\ "Software"), to deal in the Software without restriction, including
|
||||
\ without limitation the rights to use, copy, modify, merge, publish,
|
||||
\ distribute, sublicense, and/or sell copies of the Software, and to
|
||||
\ permit persons to whom the Software is furnished to do so, subject to
|
||||
\ the following conditions:
|
||||
\
|
||||
\ The above copyright notice and this permission notice shall be
|
||||
\ included in all copies or substantial portions of the Software.
|
||||
\
|
||||
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
\ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
\ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
\ SOFTWARE.
|
||||
|
||||
\ ----------------------------------------------------------------------
|
||||
\ Handshake processing code, for the client.
|
||||
\ The common T0 code (ssl_hs_common.t0) shall be read first.
|
||||
|
||||
preamble {
|
||||
|
||||
/*
|
||||
* This macro evaluates to a pointer to the client context, under that
|
||||
* specific name. It must be noted that since the engine context is the
|
||||
* first field of the br_ssl_client_context structure ('eng'), then
|
||||
* pointers values of both types are interchangeable, modulo an
|
||||
* appropriate cast. This also means that "adresses" computed as offsets
|
||||
* within the structure work for both kinds of context.
|
||||
*/
|
||||
#define CTX ((br_ssl_client_context *)ENG)
|
||||
|
||||
/*
|
||||
* Generate the pre-master secret for RSA key exchange, and encrypt it
|
||||
* with the server's public key. Returned value is either the encrypted
|
||||
* data length (in bytes), or -x on error, with 'x' being an error code.
|
||||
*
|
||||
* This code assumes that the public key has been already verified (it
|
||||
* was properly obtained by the X.509 engine, and it has the right type,
|
||||
* i.e. it is of type RSA and suitable for encryption).
|
||||
*/
|
||||
static int
|
||||
make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
|
||||
{
|
||||
const br_x509_class **xc;
|
||||
const br_x509_pkey *pk;
|
||||
const unsigned char *n;
|
||||
unsigned char *pms;
|
||||
size_t nlen, u;
|
||||
|
||||
xc = ctx->eng.x509ctx;
|
||||
pk = (*xc)->get_pkey(xc);
|
||||
|
||||
/*
|
||||
* Compute actual RSA key length, in case there are leading zeros.
|
||||
*/
|
||||
n = pk->key.rsa.n;
|
||||
nlen = pk->key.rsa.nlen;
|
||||
while (nlen > 0 && *n == 0) {
|
||||
n ++;
|
||||
nlen --;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need at least 59 bytes (48 bytes for pre-master secret, and
|
||||
* 11 bytes for the PKCS#1 type 2 padding). Note that the X.509
|
||||
* minimal engine normally blocks RSA keys shorter than 128 bytes,
|
||||
* so this is mostly for public keys provided explicitly by the
|
||||
* caller.
|
||||
*/
|
||||
if (nlen < 59) {
|
||||
return -BR_ERR_X509_WEAK_PUBLIC_KEY;
|
||||
}
|
||||
if (nlen > sizeof ctx->eng.pad) {
|
||||
return -BR_ERR_LIMIT_EXCEEDED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make PMS.
|
||||
*/
|
||||
pms = ctx->eng.pad + nlen - 48;
|
||||
br_enc16be(pms, ctx->eng.version_max);
|
||||
br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46);
|
||||
br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48);
|
||||
|
||||
/*
|
||||
* Apply PKCS#1 type 2 padding.
|
||||
*/
|
||||
ctx->eng.pad[0] = 0x00;
|
||||
ctx->eng.pad[1] = 0x02;
|
||||
ctx->eng.pad[nlen - 49] = 0x00;
|
||||
br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51);
|
||||
for (u = 2; u < nlen - 49; u ++) {
|
||||
while (ctx->eng.pad[u] == 0) {
|
||||
br_hmac_drbg_generate(&ctx->eng.rng,
|
||||
&ctx->eng.pad[u], 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute RSA encryption.
|
||||
*/
|
||||
if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) {
|
||||
return -BR_ERR_LIMIT_EXCEEDED;
|
||||
}
|
||||
return (int)nlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* OID for hash functions in RSA signatures.
|
||||
*/
|
||||
static const unsigned char HASH_OID_SHA1[] = {
|
||||
0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
|
||||
};
|
||||
|
||||
static const unsigned char HASH_OID_SHA224[] = {
|
||||
0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
|
||||
};
|
||||
|
||||
static const unsigned char HASH_OID_SHA256[] = {
|
||||
0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||
};
|
||||
|
||||
static const unsigned char HASH_OID_SHA384[] = {
|
||||
0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||
};
|
||||
|
||||
static const unsigned char HASH_OID_SHA512[] = {
|
||||
0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||
};
|
||||
|
||||
static const unsigned char *HASH_OID[] = {
|
||||
HASH_OID_SHA1,
|
||||
HASH_OID_SHA224,
|
||||
HASH_OID_SHA256,
|
||||
HASH_OID_SHA384,
|
||||
HASH_OID_SHA512
|
||||
};
|
||||
|
||||
/*
|
||||
* Check the RSA signature on the ServerKeyExchange message.
|
||||
* hash hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
|
||||
* use_rsa non-zero for RSA signature, zero for ECDSA
|
||||
* sig_len signature length (in bytes); signature value is in the pad
|
||||
* Returned value is 0 on success, or an error code.
|
||||
*/
|
||||
static int
|
||||
verify_SKE_sig(br_ssl_client_context *ctx,
|
||||
int hash, int use_rsa, size_t sig_len)
|
||||
{
|
||||
const br_x509_class **xc;
|
||||
const br_x509_pkey *pk;
|
||||
br_multihash_context mhc;
|
||||
unsigned char hv[64], head[4];
|
||||
size_t hv_len;
|
||||
|
||||
xc = ctx->eng.x509ctx;
|
||||
pk = (*xc)->get_pkey(xc);
|
||||
br_multihash_zero(&mhc);
|
||||
br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
|
||||
br_multihash_init(&mhc);
|
||||
br_multihash_update(&mhc,
|
||||
ctx->eng.client_random, sizeof ctx->eng.client_random);
|
||||
br_multihash_update(&mhc,
|
||||
ctx->eng.server_random, sizeof ctx->eng.server_random);
|
||||
head[0] = 3;
|
||||
head[1] = 0;
|
||||
head[2] = ctx->eng.ecdhe_curve;
|
||||
head[3] = ctx->eng.ecdhe_point_len;
|
||||
br_multihash_update(&mhc, head, sizeof head);
|
||||
br_multihash_update(&mhc,
|
||||
ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
|
||||
if (hash) {
|
||||
hv_len = br_multihash_out(&mhc, hash, hv);
|
||||
if (hv_len == 0) {
|
||||
return BR_ERR_INVALID_ALGORITHM;
|
||||
}
|
||||
} else {
|
||||
if (!br_multihash_out(&mhc, br_md5_ID, hv)
|
||||
|| !br_multihash_out(&mhc, br_sha1_ID, hv + 16))
|
||||
{
|
||||
return BR_ERR_INVALID_ALGORITHM;
|
||||
}
|
||||
hv_len = 36;
|
||||
}
|
||||
if (use_rsa) {
|
||||
unsigned char tmp[64];
|
||||
const unsigned char *hash_oid;
|
||||
|
||||
if (hash) {
|
||||
hash_oid = HASH_OID[hash - 2];
|
||||
} else {
|
||||
hash_oid = NULL;
|
||||
}
|
||||
if (!ctx->irsavrfy(ctx->eng.pad, sig_len,
|
||||
hash_oid, hv_len, &pk->key.rsa, tmp)
|
||||
|| memcmp(tmp, hv, hv_len) != 0)
|
||||
{
|
||||
return BR_ERR_BAD_SIGNATURE;
|
||||
}
|
||||
} else {
|
||||
if (!ctx->iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
|
||||
ctx->eng.pad, sig_len))
|
||||
{
|
||||
return BR_ERR_BAD_SIGNATURE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform client-size ECDH (or ECDHE). The point that should be sent to
|
||||
* the server is written in the pad; returned value is either the point
|
||||
* length (in bytes), or -x on error, with 'x' being an error code.
|
||||
*
|
||||
* The point _from_ the server is taken from ecdhe_point[] if 'ecdhe'
|
||||
* is non-zero, or from the X.509 engine context if 'ecdhe' is zero
|
||||
* (for static ECDH).
|
||||
*/
|
||||
static int
|
||||
make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
|
||||
{
|
||||
int curve;
|
||||
unsigned char key[66], point[133];
|
||||
const unsigned char *generator, *order, *point_src;
|
||||
size_t glen, olen, point_len;
|
||||
unsigned char mask;
|
||||
|
||||
if (ecdhe) {
|
||||
curve = ctx->eng.ecdhe_curve;
|
||||
point_src = ctx->eng.ecdhe_point;
|
||||
point_len = ctx->eng.ecdhe_point_len;
|
||||
} else {
|
||||
const br_x509_class **xc;
|
||||
const br_x509_pkey *pk;
|
||||
|
||||
xc = ctx->eng.x509ctx;
|
||||
pk = (*xc)->get_pkey(xc);
|
||||
curve = pk->key.ec.curve;
|
||||
point_src = pk->key.ec.q;
|
||||
point_len = pk->key.ec.qlen;
|
||||
}
|
||||
if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) {
|
||||
return -BR_ERR_INVALID_ALGORITHM;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to generate our key, as a non-zero random value which
|
||||
* is lower than the curve order, in a "large enough" range. We
|
||||
* force top bit to 0 and bottom bit to 1, which guarantees that
|
||||
* the value is in the proper range.
|
||||
*/
|
||||
order = ctx->eng.iec->order(curve, &olen);
|
||||
mask = 0xFF;
|
||||
while (mask >= order[0]) {
|
||||
mask >>= 1;
|
||||
}
|
||||
br_hmac_drbg_generate(&ctx->eng.rng, key, olen);
|
||||
key[0] &= mask;
|
||||
key[olen - 1] |= 0x01;
|
||||
|
||||
/*
|
||||
* Compute the common ECDH point, whose X coordinate is the
|
||||
* pre-master secret.
|
||||
*/
|
||||
generator = ctx->eng.iec->generator(curve, &glen);
|
||||
if (glen != point_len) {
|
||||
return -BR_ERR_INVALID_ALGORITHM;
|
||||
}
|
||||
|
||||
memcpy(point, point_src, glen);
|
||||
if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) {
|
||||
return -BR_ERR_INVALID_ALGORITHM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The pre-master secret is the X coordinate.
|
||||
*/
|
||||
br_ssl_engine_compute_master(&ctx->eng, prf_id, point + 1, glen >> 1);
|
||||
|
||||
memcpy(point, generator, glen);
|
||||
if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) {
|
||||
return -BR_ERR_INVALID_ALGORITHM;
|
||||
}
|
||||
memcpy(ctx->eng.pad, point, glen);
|
||||
return (int)glen;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
\ =======================================================================
|
||||
|
||||
: addr-ctx:
|
||||
next-word { field }
|
||||
"addr-" field + 0 1 define-word
|
||||
0 8191 "offsetof(br_ssl_client_context, " field + ")" + make-CX
|
||||
postpone literal postpone ; ;
|
||||
|
||||
\ Length of the Secure Renegotiation extension. This is 5 for the
|
||||
\ first handshake, 17 for a renegotiation (if the server supports the
|
||||
\ extension), or 0 if we know that the server does not support the
|
||||
\ extension.
|
||||
: ext-reneg-length ( -- n )
|
||||
addr-reneg get8 dup if 1 - 17 * else drop 5 then ;
|
||||
|
||||
\ Length of SNI extension.
|
||||
: ext-sni-length ( -- len )
|
||||
addr-server_name strlen dup if 9 + then ;
|
||||
|
||||
\ Length of Maximum Fragment Length extension.
|
||||
: ext-frag-length ( -- len )
|
||||
addr-log_max_frag_len get8 14 = if 0 else 5 then ;
|
||||
|
||||
\ Test support for RSA signatures.
|
||||
cc: supports-rsa-sign? ( -- bool ) {
|
||||
T0_PUSHi(-(CTX->irsavrfy != 0));
|
||||
}
|
||||
|
||||
\ Test support for ECDSA signatures.
|
||||
cc: supports-ecdsa? ( -- bool ) {
|
||||
T0_PUSHi(-(CTX->iecdsa != 0));
|
||||
}
|
||||
|
||||
\ Length of Signatures extension.
|
||||
: ext-signatures-length ( -- len )
|
||||
supported-hash-functions { x } drop
|
||||
0
|
||||
supports-rsa-sign? if x + then
|
||||
supports-ecdsa? if x + then
|
||||
dup if 1 << 6 + then ;
|
||||
|
||||
\ Write supported hash functions ( sign -- )
|
||||
: write-hashes
|
||||
{ sign }
|
||||
supported-hash-functions drop
|
||||
\ We advertise hash functions in the following preference order:
|
||||
\ SHA-256 SHA-224 SHA-384 SHA-512 SHA-1
|
||||
\ Rationale:
|
||||
\ -- SHA-256 and SHA-224 are more efficient on 32-bit architectures
|
||||
\ -- SHA-1 is less than ideally collision-resistant
|
||||
dup 0x10 and if 4 write8 sign write8 then
|
||||
dup 0x08 and if 3 write8 sign write8 then
|
||||
dup 0x20 and if 5 write8 sign write8 then
|
||||
dup 0x40 and if 6 write8 sign write8 then
|
||||
0x04 and if 2 write8 sign write8 then ;
|
||||
|
||||
\ Length of Supported Curves extension.
|
||||
: ext-supported-curves-length ( -- len )
|
||||
supported-curves dup if
|
||||
0 { x }
|
||||
begin dup while
|
||||
dup 1 and x + >x
|
||||
1 >>
|
||||
repeat
|
||||
drop x 1 << 6 +
|
||||
then ;
|
||||
|
||||
\ Length of Supported Point Formats extension.
|
||||
: ext-point-format-length ( -- len )
|
||||
supported-curves if 6 else 0 then ;
|
||||
|
||||
\ Write handshake message: ClientHello
|
||||
: write-ClientHello ( -- )
|
||||
{ ; total-ext-length }
|
||||
|
||||
\ Compute length for extensions (without the general two-byte header)
|
||||
ext-reneg-length ext-sni-length + ext-frag-length +
|
||||
ext-signatures-length +
|
||||
ext-supported-curves-length + ext-point-format-length +
|
||||
>total-ext-length
|
||||
|
||||
\ ClientHello type
|
||||
1 write8
|
||||
|
||||
\ Compute and write length
|
||||
39 addr-session_id_len get8 + addr-suites_num get8 1 << +
|
||||
total-ext-length if 2+ total-ext-length + then
|
||||
write24
|
||||
|
||||
\ Protocol version
|
||||
addr-version_max get16 write16
|
||||
|
||||
\ Client random
|
||||
addr-client_random 4 bzero
|
||||
addr-client_random 4 + 28 mkrand
|
||||
addr-client_random 32 write-blob
|
||||
|
||||
\ Session ID
|
||||
addr-session_id addr-session_id_len get8 write-blob-head8
|
||||
|
||||
\ Supported cipher suites. We also check here that we indeed
|
||||
\ support all these suites.
|
||||
addr-suites_num get8 dup 1 << write16
|
||||
addr-suites_buf swap
|
||||
begin
|
||||
dup while 1-
|
||||
over get16
|
||||
dup suite-supported? ifnot ERR_BAD_CIPHER_SUITE fail then
|
||||
write16
|
||||
swap 2+ swap
|
||||
repeat
|
||||
2drop
|
||||
|
||||
\ Compression methods (only "null" compression)
|
||||
1 write8 0 write8
|
||||
|
||||
\ Extensions
|
||||
total-ext-length if
|
||||
total-ext-length write16
|
||||
ext-reneg-length if
|
||||
0xFF01 write16 \ extension type (0xFF01)
|
||||
addr-saved_finished
|
||||
ext-reneg-length 4 - dup write16 \ extension length
|
||||
1- write-blob-head8 \ verify data
|
||||
then
|
||||
ext-sni-length if
|
||||
0x0000 write16 \ extension type (0)
|
||||
addr-server_name
|
||||
ext-sni-length 4 - dup write16 \ extension length
|
||||
2 - dup write16 \ ServerNameList length
|
||||
0 write8 \ name type: host_name
|
||||
3 - write-blob-head16 \ the name itself
|
||||
then
|
||||
ext-frag-length if
|
||||
0x0001 write16 \ extension type (1)
|
||||
0x0001 write16 \ extension length
|
||||
addr-log_max_frag_len get8 8 - write8
|
||||
then
|
||||
ext-signatures-length if
|
||||
0x000D write16 \ extension type (13)
|
||||
ext-signatures-length 4 - dup write16 \ extension length
|
||||
2 - write16 \ list length
|
||||
supports-ecdsa? if 3 write-hashes then
|
||||
supports-rsa-sign? if 1 write-hashes then
|
||||
then
|
||||
\ TODO: add an API to specify preference order for curves.
|
||||
\ Right now we use increasing id order, which makes P-256
|
||||
\ the preferred curve.
|
||||
ext-supported-curves-length dup if
|
||||
0x000A write16 \ extension type (10)
|
||||
4 - dup write16 \ extension length
|
||||
2- write16 \ list length
|
||||
supported-curves 0
|
||||
begin dup 32 < while
|
||||
dup2 >> 1 and if dup write16 then
|
||||
1+
|
||||
repeat
|
||||
2drop
|
||||
else
|
||||
drop
|
||||
then
|
||||
ext-point-format-length if
|
||||
0x000B write16 \ extension type (11)
|
||||
0x0002 write16 \ extension length
|
||||
0x0100 write16 \ value: 1 format: uncompressed
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
\ =======================================================================
|
||||
|
||||
\ Parse server SNI extension. If present, then it should be empty.
|
||||
: read-server-sni ( lim -- lim )
|
||||
read16 if ERR_BAD_SNI fail then ;
|
||||
|
||||
\ Parse server Max Fragment Length extension. If present, then it should
|
||||
\ advertise the same length as the client. Note that whether the server
|
||||
\ sends it or not changes nothing for us: we won't send any record larger
|
||||
\ than the advertised value anyway, and we will accept incoming records
|
||||
\ up to our input buffer length.
|
||||
: read-server-frag ( lim -- lim )
|
||||
read16 1 = ifnot ERR_BAD_FRAGLEN fail then
|
||||
read8 8 + addr-log_max_frag_len get8 = ifnot ERR_BAD_FRAGLEN fail then ;
|
||||
|
||||
\ Parse server Secure Renegotiation extension. This is called only if
|
||||
\ the client sent that extension, so we only have two cases to
|
||||
\ distinguish: first handshake, and renegotiation; in the latter case,
|
||||
\ we know that the server supports the extension, otherwise the client
|
||||
\ would not have sent it.
|
||||
: read-server-reneg ( lim -- lim )
|
||||
read16
|
||||
addr-reneg get8 ifnot
|
||||
\ "reneg" is 0, so this is a first handshake. The server's
|
||||
\ extension MUST be empty. We also learn that the server
|
||||
\ supports the extension.
|
||||
1 = ifnot ERR_BAD_SECRENEG fail then
|
||||
read8 0 = ifnot ERR_BAD_SECRENEG fail then
|
||||
2 addr-reneg set8
|
||||
else
|
||||
\ "reneg" is non-zero, and we sent an extension, so it must
|
||||
\ be 2 and this is a renegotiation. We must verify that
|
||||
\ the extension contents have length exactly 24 bytes and
|
||||
\ match the saved client and server "Finished".
|
||||
25 = ifnot ERR_BAD_SECRENEG fail then
|
||||
read8 24 = ifnot ERR_BAD_SECRENEG fail then
|
||||
addr-pad 24 read-blob
|
||||
addr-saved_finished addr-pad 24 memcmp ifnot
|
||||
ERR_BAD_SECRENEG fail
|
||||
then
|
||||
then ;
|
||||
|
||||
\ Save a value in a 16-bit field, or check it in case of session resumption.
|
||||
: check-resume ( val addr resume -- )
|
||||
if get16 = ifnot ERR_RESUME_MISMATCH fail then else set16 then ;
|
||||
|
||||
cc: DEBUG-BLOB ( addr len -- ) {
|
||||
extern int printf(const char *fmt, ...);
|
||||
|
||||
size_t len = T0_POP();
|
||||
unsigned char *buf = (unsigned char *)CTX + T0_POP();
|
||||
size_t u;
|
||||
|
||||
printf("BLOB:");
|
||||
for (u = 0; u < len; u ++) {
|
||||
if (u % 16 == 0) {
|
||||
printf("\n ");
|
||||
}
|
||||
printf(" %02x", buf[u]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
\ Parse incoming ServerHello. Returned value is true (-1) on session
|
||||
\ resumption.
|
||||
: read-ServerHello ( -- bool )
|
||||
\ Get header, and check message type.
|
||||
read-handshake-header 2 = ifnot ERR_UNEXPECTED fail then
|
||||
|
||||
\ Get protocol version.
|
||||
read16 { version }
|
||||
version addr-version_min get16 < version addr-version_max get16 > or if
|
||||
ERR_UNSUPPORTED_VERSION fail
|
||||
then
|
||||
|
||||
\ Enforce chosen version for subsequent records in both directions.
|
||||
version addr-version_in get16 <> if ERR_BAD_VERSION fail then
|
||||
version addr-version_out set16
|
||||
|
||||
\ Server random.
|
||||
addr-server_random 32 read-blob
|
||||
|
||||
\ The "session resumption" flag.
|
||||
0 { resume }
|
||||
|
||||
\ Session ID.
|
||||
read8 { idlen }
|
||||
idlen 32 > if ERR_OVERSIZED_ID fail then
|
||||
addr-pad idlen read-blob
|
||||
idlen addr-session_id_len get8 = idlen 0 > and if
|
||||
addr-session_id addr-pad idlen memcmp if
|
||||
\ Server session ID is non-empty and matches what
|
||||
\ we sent, so this is a session resumption.
|
||||
-1 >resume
|
||||
then
|
||||
then
|
||||
addr-session_id addr-pad idlen memcpy
|
||||
idlen addr-session_id_len set8
|
||||
|
||||
\ Record version.
|
||||
version addr-version resume check-resume
|
||||
|
||||
\ Cipher suite. We check that it is part of the list of cipher
|
||||
\ suites that we advertised.
|
||||
\ read16 { suite ; found }
|
||||
\ 0 >found
|
||||
\ addr-suites_buf dup addr-suites_num get8 1 << +
|
||||
\ begin dup2 < while
|
||||
\ 2 - dup get16
|
||||
\ suite = found or >found
|
||||
\ repeat
|
||||
\ 2drop found ifnot ERR_BAD_CIPHER_SUITE fail then
|
||||
read16
|
||||
dup scan-suite 0< if ERR_BAD_CIPHER_SUITE fail then
|
||||
addr-cipher_suite resume check-resume
|
||||
|
||||
\ Compression method. Should be 0 (no compression).
|
||||
read8 if ERR_BAD_COMPRESSION fail then
|
||||
|
||||
\ Parse extensions (if any). If there is no extension, then the
|
||||
\ read limit (on the TOS) should be 0 at that point.
|
||||
dup if
|
||||
\ Length of extension list.
|
||||
\ message size.
|
||||
read16 open-elt
|
||||
|
||||
\ Enumerate extensions. For each of them, check that we
|
||||
\ sent an extension of that type, and did not see it
|
||||
\ yet; and then process it.
|
||||
ext-sni-length { ok-sni }
|
||||
ext-reneg-length { ok-reneg }
|
||||
ext-frag-length { ok-frag }
|
||||
ext-signatures-length { ok-signatures }
|
||||
ext-supported-curves-length { ok-curves }
|
||||
ext-point-format-length { ok-points }
|
||||
begin dup while
|
||||
read16
|
||||
case
|
||||
\ Server Name Indication. The server may
|
||||
\ send such an extension if it uses the SNI
|
||||
\ from the client, but that "response
|
||||
\ extension" is supposed to be empty.
|
||||
0x0000 of
|
||||
ok-sni ifnot
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
then
|
||||
0 >ok-sni
|
||||
read-server-sni
|
||||
endof
|
||||
|
||||
\ Max Frag Length. The contents shall be
|
||||
\ a single byte whose value matches the one
|
||||
\ sent by the client.
|
||||
0x0001 of
|
||||
ok-frag ifnot
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
then
|
||||
0 >ok-frag
|
||||
read-server-frag
|
||||
endof
|
||||
|
||||
\ Secure Renegotiation.
|
||||
0xFF01 of
|
||||
ok-reneg ifnot
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
then
|
||||
0 >ok-reneg
|
||||
read-server-reneg
|
||||
endof
|
||||
|
||||
\ Signature Algorithms.
|
||||
\ Normally, the server should never send this
|
||||
\ extension (so says RFC 5246 #7.4.1.4.1),
|
||||
\ but some existing servers do.
|
||||
0x000D of
|
||||
ok-signatures ifnot
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
then
|
||||
0 >ok-signatures
|
||||
read-ignore-16
|
||||
endof
|
||||
|
||||
\ Supported Curves.
|
||||
0x000A of
|
||||
ok-curves ifnot
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
then
|
||||
0 >ok-curves
|
||||
read-ignore-16
|
||||
endof
|
||||
|
||||
\ Supported Point Formats.
|
||||
0x000B of
|
||||
ok-points ifnot
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
then
|
||||
0 >ok-points
|
||||
read-ignore-16
|
||||
endof
|
||||
|
||||
ERR_EXTRA_EXTENSION fail
|
||||
endcase
|
||||
repeat
|
||||
|
||||
\ If we sent a secure renegotiation extension but did not
|
||||
\ receive a response, then the server does not support
|
||||
\ secure renegotiation. This is a hard failure if this
|
||||
\ is a renegotiation.
|
||||
ok-reneg if
|
||||
ok-reneg 5 > if ERR_BAD_SECRENEG fail then
|
||||
1 addr-reneg set8
|
||||
then
|
||||
close-elt
|
||||
then
|
||||
close-elt
|
||||
resume
|
||||
;
|
||||
|
||||
cc: x509-start-chain ( expected-key-type -- ) {
|
||||
const br_x509_class *xc;
|
||||
|
||||
xc = *(ENG->x509ctx);
|
||||
xc->start_chain(ENG->x509ctx, T0_POP(), ENG->server_name);
|
||||
}
|
||||
|
||||
cc: x509-start-cert ( length -- ) {
|
||||
const br_x509_class *xc;
|
||||
|
||||
xc = *(ENG->x509ctx);
|
||||
xc->start_cert(ENG->x509ctx, T0_POP());
|
||||
}
|
||||
|
||||
cc: x509-append ( length -- ) {
|
||||
const br_x509_class *xc;
|
||||
size_t len;
|
||||
|
||||
xc = *(ENG->x509ctx);
|
||||
len = T0_POP();
|
||||
xc->append(ENG->x509ctx, ENG->pad, len);
|
||||
}
|
||||
|
||||
cc: x509-end-cert ( -- ) {
|
||||
const br_x509_class *xc;
|
||||
|
||||
xc = *(ENG->x509ctx);
|
||||
xc->end_cert(ENG->x509ctx);
|
||||
}
|
||||
|
||||
cc: x509-end-chain ( -- err ) {
|
||||
const br_x509_class *xc;
|
||||
|
||||
xc = *(ENG->x509ctx);
|
||||
T0_PUSH(xc->end_chain(ENG->x509ctx));
|
||||
}
|
||||
|
||||
\ Parse Certificate
|
||||
: read-Certificate ( -- )
|
||||
\ Get header, and check message type.
|
||||
read-handshake-header 11 = ifnot ERR_UNEXPECTED fail then
|
||||
|
||||
\ Start processing the chain through the X.509 engine.
|
||||
addr-cipher_suite get16 expected-key-type
|
||||
x509-start-chain
|
||||
|
||||
\ Total chain length is a 24-bit integer.
|
||||
read24 open-elt
|
||||
begin
|
||||
dup while
|
||||
read24 open-elt
|
||||
dup x509-start-cert
|
||||
|
||||
\ We read the certificate by chunks through the pad, so
|
||||
\ as to use the existing reading function (read-blob)
|
||||
\ that also ensures proper hashing.
|
||||
begin
|
||||
dup while
|
||||
dup 256 > if 256 else dup then { len }
|
||||
addr-pad len read-blob
|
||||
len x509-append
|
||||
repeat
|
||||
close-elt
|
||||
x509-end-cert
|
||||
repeat
|
||||
|
||||
\ We must close the chain AND the handshake message.
|
||||
close-elt
|
||||
close-elt
|
||||
|
||||
\ Chain processing is finished; get the error code.
|
||||
x509-end-chain
|
||||
dup if fail then drop
|
||||
;
|
||||
|
||||
\ Verify signature on ECDHE point sent by the server.
|
||||
\ 'hash' is the hash function to use (1 to 6, or 0 for RSA with MD5+SHA-1)
|
||||
\ 'use-rsa' is 0 for ECDSA, -1 for for RSA
|
||||
\ 'sig-len' is the signature length (in bytes)
|
||||
\ The signature itself is in the pad.
|
||||
cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) {
|
||||
size_t sig_len = T0_POP();
|
||||
int use_rsa = T0_POPi();
|
||||
int hash = T0_POPi();
|
||||
|
||||
T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len));
|
||||
}
|
||||
|
||||
\ Parse ServerKeyExchange
|
||||
: read-ServerKeyExchange ( -- )
|
||||
\ Get header, and check message type.
|
||||
read-handshake-header 12 = ifnot ERR_UNEXPECTED fail then
|
||||
|
||||
\ We expect a named curve, and we must support it.
|
||||
read8 3 = ifnot ERR_INVALID_ALGORITHM fail then
|
||||
read16 dup addr-ecdhe_curve set8
|
||||
dup 32 >= if ERR_INVALID_ALGORITHM fail then
|
||||
supported-curves swap >> 1 and ifnot ERR_INVALID_ALGORITHM fail then
|
||||
|
||||
\ Read the server point.
|
||||
read8
|
||||
dup 133 > if ERR_INVALID_ALGORITHM fail then
|
||||
dup addr-ecdhe_point_len set8
|
||||
addr-ecdhe_point swap read-blob
|
||||
|
||||
\ If using TLS-1.2+, then the hash function and signature algorithm
|
||||
\ are explicitly provided; the signature algorithm must match what
|
||||
\ the cipher suite specifies. With TLS-1.0 and 1.1, the signature
|
||||
\ algorithm is inferred from the cipher suite, and the hash is
|
||||
\ either MD5+SHA-1 (for RSA signatures) or SHA-1 (for ECDSA).
|
||||
addr-version get16 0x0303 >= { tls1.2+ }
|
||||
addr-cipher_suite get16 use-rsa-ecdhe? { use-rsa }
|
||||
2 { hash }
|
||||
tls1.2+ if
|
||||
\ Read hash function; accept only the SHA-* identifiers
|
||||
\ (from SHA-1 to SHA-512, no MD5 here).
|
||||
read8
|
||||
dup dup 2 < swap 6 > or if ERR_INVALID_ALGORITHM fail then
|
||||
>hash
|
||||
read8
|
||||
\ Get expected signature algorithm and compare with what
|
||||
\ the server just sent. Expected value is 1 for RSA, 3
|
||||
\ for ECDSA. Note that 'use-rsa' evaluates to -1 for RSA,
|
||||
\ 0 for ECDSA.
|
||||
use-rsa 1 << 3 + = ifnot ERR_INVALID_ALGORITHM fail then
|
||||
else
|
||||
\ For MD5+SHA-1, we set 'hash' to 0.
|
||||
use-rsa if 0 >hash then
|
||||
then
|
||||
|
||||
\ Read signature into the pad.
|
||||
read16 dup { sig-len }
|
||||
|
||||
dup 512 > if ERR_LIMIT_EXCEEDED fail then
|
||||
addr-pad swap read-blob
|
||||
|
||||
\ Verify signature.
|
||||
hash use-rsa sig-len verify-SKE-sig
|
||||
dup if fail then drop
|
||||
|
||||
close-elt ;
|
||||
|
||||
\ Parse CertificateRequest. Header has already been read.
|
||||
: read-contents-CertificateRequest ( lim -- )
|
||||
\ TODO: implement client certificates. Right now, we simply
|
||||
\ drop the complete message.
|
||||
begin dup while read8 drop repeat drop ;
|
||||
|
||||
\ Write an empty Certificate message.
|
||||
: write-empty-Certificate ( -- )
|
||||
11 write8 3 write24 0 write24 ;
|
||||
|
||||
cc: do-rsa-encrypt ( prf_id -- nlen ) {
|
||||
int x;
|
||||
|
||||
x = make_pms_rsa(CTX, T0_POP());
|
||||
if (x < 0) {
|
||||
br_ssl_engine_fail(ENG, -x);
|
||||
T0_CO();
|
||||
} else {
|
||||
T0_PUSH(x);
|
||||
}
|
||||
}
|
||||
|
||||
cc: do-ecdh ( echde prf_id -- ulen ) {
|
||||
unsigned prf_id = T0_POP();
|
||||
unsigned ecdhe = T0_POP();
|
||||
int x;
|
||||
|
||||
x = make_pms_ecdh(CTX, ecdhe, prf_id);
|
||||
if (x < 0) {
|
||||
br_ssl_engine_fail(ENG, -x);
|
||||
T0_CO();
|
||||
} else {
|
||||
T0_PUSH(x);
|
||||
}
|
||||
}
|
||||
|
||||
\ Write ClientKeyExchange
|
||||
: write-ClientKeyExchange ( -- )
|
||||
16 write8
|
||||
addr-cipher_suite get16
|
||||
dup use-rsa-keyx? if
|
||||
prf-id do-rsa-encrypt
|
||||
dup 2+ write24
|
||||
dup write16
|
||||
addr-pad swap write-blob
|
||||
else
|
||||
dup use-ecdhe? swap prf-id do-ecdh
|
||||
dup 1+ write24
|
||||
dup write8
|
||||
addr-pad swap write-blob
|
||||
then ;
|
||||
|
||||
\ =======================================================================
|
||||
|
||||
\ Perform a handshake.
|
||||
: do-handshake ( -- )
|
||||
0 addr-application_data set8
|
||||
22 addr-record_type_out set8
|
||||
multihash-init
|
||||
|
||||
write-ClientHello
|
||||
flush-record
|
||||
read-ServerHello
|
||||
|
||||
if
|
||||
\ Session resumption.
|
||||
-1 read-CCS-Finished
|
||||
-1 write-CCS-Finished
|
||||
|
||||
else
|
||||
|
||||
\ Not a session resumption.
|
||||
|
||||
read-Certificate
|
||||
|
||||
\ Depending on cipher suite, we may now expect a
|
||||
\ ServerKeyExchange.
|
||||
addr-cipher_suite get16 expected-key-type
|
||||
CX 0 63 { BR_KEYTYPE_SIGN } and if
|
||||
read-ServerKeyExchange
|
||||
then
|
||||
|
||||
\ Get next header.
|
||||
read-handshake-header
|
||||
|
||||
\ If this is a CertificateRequest, parse it, then read
|
||||
\ next header.
|
||||
dup 13 = if
|
||||
drop read-contents-CertificateRequest
|
||||
read-handshake-header
|
||||
-1
|
||||
else
|
||||
0
|
||||
then
|
||||
{ seen-CR }
|
||||
|
||||
\ At that point, we should have a ServerHelloDone,
|
||||
\ whose length must be 0.
|
||||
14 = ifnot ERR_UNEXPECTED fail then
|
||||
if ERR_BAD_HELLO_DONE fail then
|
||||
|
||||
\ There should not be more bytes in the record at that point.
|
||||
more-incoming-bytes? if ERR_UNEXPECTED fail then
|
||||
|
||||
seen-CR if
|
||||
\ TODO: client certificate support.
|
||||
write-empty-Certificate
|
||||
then
|
||||
write-ClientKeyExchange
|
||||
|
||||
\ TODO: CertificateVerify
|
||||
|
||||
-1 write-CCS-Finished
|
||||
-1 read-CCS-Finished
|
||||
then
|
||||
|
||||
\ Now we should be invoked only in case of renegotiation.
|
||||
1 addr-application_data set8
|
||||
23 addr-record_type_out set8 ;
|
||||
|
||||
\ Read a HelloRequest message.
|
||||
: read-HelloRequest ( -- )
|
||||
\ A HelloRequest has length 0 and type 0.
|
||||
read-handshake-header-core
|
||||
if ERR_UNEXPECTED fail then
|
||||
if ERR_BAD_HANDSHAKE fail then ;
|
||||
|
||||
\ Entry point.
|
||||
: main ( -- ! )
|
||||
\ Perform initial handshake.
|
||||
do-handshake
|
||||
|
||||
begin
|
||||
\ Wait for further invocation. At that point, we should
|
||||
\ get either an explicit call for renegotiation, or
|
||||
\ an incoming HelloRequest handshake message.
|
||||
wait-co
|
||||
dup 0x07 and case
|
||||
0x00 of
|
||||
0x10 and if
|
||||
do-handshake
|
||||
then
|
||||
endof
|
||||
0x01 of
|
||||
drop
|
||||
0 addr-application_data set8
|
||||
read-HelloRequest
|
||||
\ Reject renegotiations if the peer does not
|
||||
\ support secure renegotiation. Theoretically
|
||||
\ we could just ignore that, however if the
|
||||
\ server sent an HelloRequest then it is
|
||||
\ expecting a handshake and will wait for our
|
||||
\ ClientHello.
|
||||
addr-reneg get8 1 = if
|
||||
flush-record
|
||||
begin can-output? not while
|
||||
wait-co drop
|
||||
repeat
|
||||
100 send-warning
|
||||
else
|
||||
do-handshake
|
||||
then
|
||||
endof
|
||||
ERR_UNEXPECTED fail
|
||||
endcase
|
||||
again
|
||||
;
|
||||
1012
src/ssl/ssl_hs_common.t0
Normal file
1012
src/ssl/ssl_hs_common.t0
Normal file
File diff suppressed because it is too large
Load diff
1479
src/ssl/ssl_hs_server.c
Normal file
1479
src/ssl/ssl_hs_server.c
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue