Compare commits
3 Commits
SOFTOKEN_3
...
Bugzilla_P
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b52a1dc48a | ||
|
|
48b5f960fd | ||
|
|
73bf11394f |
@@ -1,71 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dbm
|
||||
|
||||
EXPORTS = \
|
||||
nsres.h \
|
||||
cdefs.h \
|
||||
mcom_db.h \
|
||||
ncompat.h \
|
||||
winfile.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
hsearch.h \
|
||||
page.h \
|
||||
extern.h \
|
||||
ndbm.h \
|
||||
queue.h \
|
||||
hash.h \
|
||||
mpool.h \
|
||||
search.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS := $(addprefix $(srcdir)/, $(PRIVATE_EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Makefile to build the cert library
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
!ifndef MOZ_DEBUG
|
||||
OPTIMIZER=-Os -UDEBUG -DNDEBUG
|
||||
!endif
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Specify the depth of the current directory relative to the
|
||||
#// root of NS
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DEPTH= ..\..
|
||||
|
||||
!ifndef MAKE_OBJ_TYPE
|
||||
MAKE_OBJ_TYPE=EXE
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// install headers
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
EXPORTS=nsres.h cdefs.h mcom_db.h ncompat.h winfile.h
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Include the common makefile rules
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
CFLAGS = $(CFLAGS) -DMOZILLA_CLIENT
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Berkeley Software Design, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cdefs.h 8.7 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
#ifndef _CDEFS_H_
|
||||
#define _CDEFS_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#define __BEGIN_DECLS extern "C" {
|
||||
#define __END_DECLS }
|
||||
#else
|
||||
#define __BEGIN_DECLS
|
||||
#define __END_DECLS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
|
||||
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
|
||||
* The __CONCAT macro is a bit tricky -- make sure you don't put spaces
|
||||
* in between its arguments. __CONCAT can also concatenate double-quoted
|
||||
* strings produced by the __STRING macro, but this only works with ANSI C.
|
||||
*/
|
||||
#if defined(__STDC__) || defined(__cplusplus) || defined(_WINDOWS) || defined(XP_OS2)
|
||||
#define __P(protos) protos /* full-blown ANSI C */
|
||||
#define __CONCAT(x,y) x ## y
|
||||
#define __STRING(x) #x
|
||||
|
||||
/* On HP-UX 11.00, <sys/stdsyms.h> defines __const. */
|
||||
#ifndef __const
|
||||
#define __const const /* define reserved names to standard */
|
||||
#endif /* __const */
|
||||
#define __signed signed
|
||||
#define __volatile volatile
|
||||
#ifndef _WINDOWS
|
||||
#if defined(__cplusplus)
|
||||
#define __inline inline /* convert to C++ keyword */
|
||||
#else
|
||||
#if !defined(__GNUC__) && !defined(__MWERKS__)
|
||||
#define __inline /* delete GCC keyword */
|
||||
#endif /* !__GNUC__ */
|
||||
#endif /* !__cplusplus */
|
||||
#endif /* !_WINDOWS */
|
||||
|
||||
#else /* !(__STDC__ || __cplusplus) */
|
||||
#define __P(protos) () /* traditional C preprocessor */
|
||||
#define __CONCAT(x,y) x/**/y
|
||||
#define __STRING(x) "x"
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __const /* delete pseudo-ANSI C keywords */
|
||||
#define __inline
|
||||
#define __signed
|
||||
#define __volatile
|
||||
/*
|
||||
* In non-ANSI C environments, new programs will want ANSI-only C keywords
|
||||
* deleted from the program and old programs will want them left alone.
|
||||
* When using a compiler other than gcc, programs using the ANSI C keywords
|
||||
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
|
||||
* When using "gcc -traditional", we assume that this is the intent; if
|
||||
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
|
||||
*/
|
||||
#ifndef NO_ANSI_KEYWORDS
|
||||
#define const /* delete ANSI C keywords */
|
||||
#define inline
|
||||
#define signed
|
||||
#define volatile
|
||||
#endif
|
||||
#endif /* !__GNUC__ */
|
||||
#endif /* !(__STDC__ || __cplusplus) */
|
||||
|
||||
/*
|
||||
* GCC1 and some versions of GCC2 declare dead (non-returning) and
|
||||
* pure (no side effects) functions using "volatile" and "const";
|
||||
* unfortunately, these then cause warnings under "-ansi -pedantic".
|
||||
* GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
|
||||
* these work for GNU C++ (modulo a slight glitch in the C++ grammar
|
||||
* in the distribution version of 2.5.5).
|
||||
*/
|
||||
#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
|
||||
#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define __dead __volatile
|
||||
#define __pure __const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Delete pseudo-keywords wherever they are not available or needed. */
|
||||
#ifndef __dead
|
||||
#define __dead
|
||||
#define __pure
|
||||
#endif
|
||||
|
||||
#endif /* !_CDEFS_H_ */
|
||||
@@ -1,63 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.4 (Berkeley) 6/16/94
|
||||
*/
|
||||
|
||||
BUFHEAD *__add_ovflpage (HTAB *, BUFHEAD *);
|
||||
int __addel (HTAB *, BUFHEAD *, const DBT *, const DBT *);
|
||||
int __big_delete (HTAB *, BUFHEAD *);
|
||||
int __big_insert (HTAB *, BUFHEAD *, const DBT *, const DBT *);
|
||||
int __big_keydata (HTAB *, BUFHEAD *, DBT *, DBT *, int);
|
||||
int __big_return (HTAB *, BUFHEAD *, int, DBT *, int);
|
||||
int __big_split (HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
|
||||
uint32, uint32, SPLIT_RETURN *);
|
||||
int __buf_free (HTAB *, int, int);
|
||||
void __buf_init (HTAB *, int);
|
||||
uint32 __call_hash (HTAB *, char *, size_t);
|
||||
int __delpair (HTAB *, BUFHEAD *, int);
|
||||
int __expand_table (HTAB *);
|
||||
int __find_bigpair (HTAB *, BUFHEAD *, int, char *, int);
|
||||
uint16 __find_last_page (HTAB *, BUFHEAD **);
|
||||
void __free_ovflpage (HTAB *, BUFHEAD *);
|
||||
BUFHEAD *__get_buf (HTAB *, uint32, BUFHEAD *, int);
|
||||
int __get_page (HTAB *, char *, uint32, int, int, int);
|
||||
int __ibitmap (HTAB *, int, int, int);
|
||||
uint32 __log2 (uint32);
|
||||
int __put_page (HTAB *, char *, uint32, int, int);
|
||||
void __reclaim_buf (HTAB *, BUFHEAD *);
|
||||
int __split_page (HTAB *, uint32, uint32);
|
||||
|
||||
/* Default hash routine. */
|
||||
extern uint32 (*__default_hash) (const void *, size_t);
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
|
||||
#endif
|
||||
@@ -1,335 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hash.h 8.3 (Berkeley) 5/31/94
|
||||
*/
|
||||
|
||||
/* Operations */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mcom_db.h"
|
||||
typedef enum {
|
||||
HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
|
||||
} ACTION;
|
||||
|
||||
/* Buffer Management structures */
|
||||
typedef struct _bufhead BUFHEAD;
|
||||
|
||||
struct _bufhead {
|
||||
BUFHEAD *prev; /* LRU links */
|
||||
BUFHEAD *next; /* LRU links */
|
||||
BUFHEAD *ovfl; /* Overflow page buffer header */
|
||||
uint32 addr; /* Address of this page */
|
||||
char *page; /* Actual page data */
|
||||
char is_disk;
|
||||
char flags;
|
||||
#define BUF_MOD 0x0001
|
||||
#define BUF_DISK 0x0002
|
||||
#define BUF_BUCKET 0x0004
|
||||
#define BUF_PIN 0x0008
|
||||
};
|
||||
|
||||
#define IS_BUCKET(X) ((X) & BUF_BUCKET)
|
||||
|
||||
typedef BUFHEAD **SEGMENT;
|
||||
|
||||
typedef int DBFILE_PTR;
|
||||
#define NO_FILE -1
|
||||
#ifdef macintosh
|
||||
#define DBFILE_OPEN(path, flag,mode) open((path), flag)
|
||||
#define EXISTS(path)
|
||||
#else
|
||||
#define DBFILE_OPEN(path, flag,mode) open((path), (flag), (mode))
|
||||
#endif
|
||||
/* Hash Table Information */
|
||||
typedef struct hashhdr { /* Disk resident portion */
|
||||
int32 magic; /* Magic NO for hash tables */
|
||||
int32 version; /* Version ID */
|
||||
uint32 lorder; /* Byte Order */
|
||||
int32 bsize; /* Bucket/Page Size */
|
||||
int32 bshift; /* Bucket shift */
|
||||
int32 dsize; /* Directory Size */
|
||||
int32 ssize; /* Segment Size */
|
||||
int32 sshift; /* Segment shift */
|
||||
int32 ovfl_point; /* Where overflow pages are being
|
||||
* allocated */
|
||||
int32 last_freed; /* Last overflow page freed */
|
||||
int32 max_bucket; /* ID of Maximum bucket in use */
|
||||
int32 high_mask; /* Mask to modulo into entire table */
|
||||
int32 low_mask; /* Mask to modulo into lower half of
|
||||
* table */
|
||||
int32 ffactor; /* Fill factor */
|
||||
int32 nkeys; /* Number of keys in hash table */
|
||||
int32 hdrpages; /* Size of table header */
|
||||
uint32 h_charkey; /* value of hash(CHARKEY) */
|
||||
#define NCACHED 32 /* number of bit maps and spare
|
||||
* points */
|
||||
int32 spares[NCACHED];/* spare pages for overflow */
|
||||
uint16 bitmaps[NCACHED]; /* address of overflow page
|
||||
* bitmaps */
|
||||
} HASHHDR;
|
||||
|
||||
typedef struct htab { /* Memory resident data structure */
|
||||
HASHHDR hdr; /* Header */
|
||||
int nsegs; /* Number of allocated segments */
|
||||
int exsegs; /* Number of extra allocated
|
||||
* segments */
|
||||
uint32 /* Hash function */
|
||||
(*hash)(const void *, size_t);
|
||||
int flags; /* Flag values */
|
||||
DBFILE_PTR fp; /* File pointer */
|
||||
char *filename;
|
||||
char *tmp_buf; /* Temporary Buffer for BIG data */
|
||||
char *tmp_key; /* Temporary Buffer for BIG keys */
|
||||
BUFHEAD *cpage; /* Current page */
|
||||
int cbucket; /* Current bucket */
|
||||
int cndx; /* Index of next item on cpage */
|
||||
int dbmerrno; /* Error Number -- for DBM
|
||||
* compatability */
|
||||
int new_file; /* Indicates if fd is backing store
|
||||
* or no */
|
||||
int save_file; /* Indicates whether we need to flush
|
||||
* file at
|
||||
* exit */
|
||||
uint32 *mapp[NCACHED]; /* Pointers to page maps */
|
||||
int nmaps; /* Initial number of bitmaps */
|
||||
int nbufs; /* Number of buffers left to
|
||||
* allocate */
|
||||
BUFHEAD bufhead; /* Header of buffer lru list */
|
||||
SEGMENT *dir; /* Hash Bucket directory */
|
||||
off_t file_size; /* in bytes */
|
||||
char is_temp; /* unlink file on close */
|
||||
char updateEOF; /* force EOF update on flush */
|
||||
} HTAB;
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
#define DATABASE_CORRUPTED_ERROR -999 /* big ugly abort, delete database */
|
||||
#define OLD_MAX_BSIZE 65536 /* 2^16 */
|
||||
#define MAX_BSIZE 32l*1024l /* 2^15 */
|
||||
#define MIN_BUFFERS 6
|
||||
#define MINHDRSIZE 512
|
||||
#define DEF_BUFSIZE 65536l /* 64 K */
|
||||
#define DEF_BUCKET_SIZE 4096
|
||||
#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */
|
||||
#define DEF_SEGSIZE 256
|
||||
#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
|
||||
#define DEF_DIRSIZE 256
|
||||
#define DEF_FFACTOR 65536l
|
||||
#define MIN_FFACTOR 4
|
||||
#define SPLTMAX 8
|
||||
#define CHARKEY "%$sniglet^&"
|
||||
#define NUMKEY 1038583l
|
||||
#define BYTE_SHIFT 3
|
||||
#define INT_TO_BYTE 2
|
||||
#define INT_BYTE_SHIFT 5
|
||||
#define ALL_SET ((uint32)0xFFFFFFFF)
|
||||
#define ALL_CLEAR 0
|
||||
|
||||
#define PTROF(X) ((ptrdiff_t)(X) == BUF_DISK ? 0 : (X))
|
||||
#define ISDISK(X) ((X) ? ((ptrdiff_t)(X) == BUF_DISK ? BUF_DISK \
|
||||
: (X)->is_disk) : 0)
|
||||
|
||||
#define BITS_PER_MAP 32
|
||||
|
||||
/* Given the address of the beginning of a big map, clear/set the nth bit */
|
||||
#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
|
||||
#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
|
||||
#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
|
||||
|
||||
/* Overflow management */
|
||||
/*
|
||||
* Overflow page numbers are allocated per split point. At each doubling of
|
||||
* the table, we can allocate extra pages. So, an overflow page number has
|
||||
* the top 5 bits indicate which split point and the lower 11 bits indicate
|
||||
* which page at that split point is indicated (pages within split points are
|
||||
* numberered starting with 1).
|
||||
*/
|
||||
|
||||
#define SPLITSHIFT 11
|
||||
#define SPLITMASK 0x7FF
|
||||
#define SPLITNUM(N) (((uint32)(N)) >> SPLITSHIFT)
|
||||
#define OPAGENUM(N) ((N) & SPLITMASK)
|
||||
#define OADDR_OF(S,O) ((uint32)((uint32)(S) << SPLITSHIFT) + (O))
|
||||
|
||||
#define BUCKET_TO_PAGE(B) \
|
||||
(B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((uint32)((B)+1))-1] : 0)
|
||||
#define OADDR_TO_PAGE(B) \
|
||||
BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
|
||||
|
||||
/*
|
||||
* page.h contains a detailed description of the page format.
|
||||
*
|
||||
* Normally, keys and data are accessed from offset tables in the top of
|
||||
* each page which point to the beginning of the key and data. There are
|
||||
* four flag values which may be stored in these offset tables which indicate
|
||||
* the following:
|
||||
*
|
||||
*
|
||||
* OVFLPAGE Rather than a key data pair, this pair contains
|
||||
* the address of an overflow page. The format of
|
||||
* the pair is:
|
||||
* OVERFLOW_PAGE_NUMBER OVFLPAGE
|
||||
*
|
||||
* PARTIAL_KEY This must be the first key/data pair on a page
|
||||
* and implies that page contains only a partial key.
|
||||
* That is, the key is too big to fit on a single page
|
||||
* so it starts on this page and continues on the next.
|
||||
* The format of the page is:
|
||||
* KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
|
||||
*
|
||||
* KEY_OFF -- offset of the beginning of the key
|
||||
* PARTIAL_KEY -- 1
|
||||
* OVFL_PAGENO - page number of the next overflow page
|
||||
* OVFLPAGE -- 0
|
||||
*
|
||||
* FULL_KEY This must be the first key/data pair on the page. It
|
||||
* is used in two cases.
|
||||
*
|
||||
* Case 1:
|
||||
* There is a complete key on the page but no data
|
||||
* (because it wouldn't fit). The next page contains
|
||||
* the data.
|
||||
*
|
||||
* Page format it:
|
||||
* KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
|
||||
*
|
||||
* KEY_OFF -- offset of the beginning of the key
|
||||
* FULL_KEY -- 2
|
||||
* OVFL_PAGENO - page number of the next overflow page
|
||||
* OVFLPAGE -- 0
|
||||
*
|
||||
* Case 2:
|
||||
* This page contains no key, but part of a large
|
||||
* data field, which is continued on the next page.
|
||||
*
|
||||
* Page format it:
|
||||
* DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
|
||||
*
|
||||
* KEY_OFF -- offset of the beginning of the data on
|
||||
* this page
|
||||
* FULL_KEY -- 2
|
||||
* OVFL_PAGENO - page number of the next overflow page
|
||||
* OVFLPAGE -- 0
|
||||
*
|
||||
* FULL_KEY_DATA
|
||||
* This must be the first key/data pair on the page.
|
||||
* There are two cases:
|
||||
*
|
||||
* Case 1:
|
||||
* This page contains a key and the beginning of the
|
||||
* data field, but the data field is continued on the
|
||||
* next page.
|
||||
*
|
||||
* Page format is:
|
||||
* KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
|
||||
*
|
||||
* KEY_OFF -- offset of the beginning of the key
|
||||
* FULL_KEY_DATA -- 3
|
||||
* OVFL_PAGENO - page number of the next overflow page
|
||||
* DATA_OFF -- offset of the beginning of the data
|
||||
*
|
||||
* Case 2:
|
||||
* This page contains the last page of a big data pair.
|
||||
* There is no key, only the tail end of the data
|
||||
* on this page.
|
||||
*
|
||||
* Page format is:
|
||||
* DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
|
||||
*
|
||||
* DATA_OFF -- offset of the beginning of the data on
|
||||
* this page
|
||||
* FULL_KEY_DATA -- 3
|
||||
* OVFL_PAGENO - page number of the next overflow page
|
||||
* OVFLPAGE -- 0
|
||||
*
|
||||
* OVFL_PAGENO and OVFLPAGE are optional (they are
|
||||
* not present if there is no next page).
|
||||
*/
|
||||
|
||||
#define OVFLPAGE 0
|
||||
#define PARTIAL_KEY 1
|
||||
#define FULL_KEY 2
|
||||
#define FULL_KEY_DATA 3
|
||||
#define REAL_KEY 4
|
||||
|
||||
/* Short hands for accessing structure */
|
||||
#undef BSIZE
|
||||
#define BSIZE hdr.bsize
|
||||
#undef BSHIFT
|
||||
#define BSHIFT hdr.bshift
|
||||
#define DSIZE hdr.dsize
|
||||
#define SGSIZE hdr.ssize
|
||||
#define SSHIFT hdr.sshift
|
||||
#define LORDER hdr.lorder
|
||||
#define OVFL_POINT hdr.ovfl_point
|
||||
#define LAST_FREED hdr.last_freed
|
||||
#define MAX_BUCKET hdr.max_bucket
|
||||
#define FFACTOR hdr.ffactor
|
||||
#define HIGH_MASK hdr.high_mask
|
||||
#define LOW_MASK hdr.low_mask
|
||||
#define NKEYS hdr.nkeys
|
||||
#define HDRPAGES hdr.hdrpages
|
||||
#define SPARES hdr.spares
|
||||
#define BITMAPS hdr.bitmaps
|
||||
#define VERSION hdr.version
|
||||
#define MAGIC hdr.magic
|
||||
#define NEXT_FREE hdr.next_free
|
||||
#define H_CHARKEY hdr.h_charkey
|
||||
|
||||
extern uint32 (*__default_hash) (const void *, size_t);
|
||||
void __buf_init(HTAB *hashp, int32 nbytes);
|
||||
int __big_delete(HTAB *hashp, BUFHEAD *bufp);
|
||||
BUFHEAD * __get_buf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp, int newpage);
|
||||
uint32 __call_hash(HTAB *hashp, char *k, size_t len);
|
||||
#include "page.h"
|
||||
extern int __big_split(HTAB *hashp, BUFHEAD *op,BUFHEAD *np,
|
||||
BUFHEAD *big_keyp,uint32 addr,uint32 obucket, SPLIT_RETURN *ret);
|
||||
void __free_ovflpage(HTAB *hashp, BUFHEAD *obufp);
|
||||
BUFHEAD * __add_ovflpage(HTAB *hashp, BUFHEAD *bufp);
|
||||
int __big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val);
|
||||
int __expand_table(HTAB *hashp);
|
||||
uint32 __log2(uint32 num);
|
||||
void __reclaim_buf(HTAB *hashp, BUFHEAD *bp);
|
||||
int __get_page(HTAB *hashp, char * p, uint32 bucket, int is_bucket, int is_disk, int is_bitmap);
|
||||
int __put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap);
|
||||
int __ibitmap(HTAB *hashp, int pnum, int nbits, int ndx);
|
||||
int __buf_free(HTAB *hashp, int do_free, int to_disk);
|
||||
int __find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size);
|
||||
uint16 __find_last_page(HTAB *hashp, BUFHEAD **bpp);
|
||||
int __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT * val);
|
||||
int __big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current);
|
||||
int __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx);
|
||||
int __big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set);
|
||||
int __split_page(HTAB *hashp, uint32 obucket, uint32 nbucket);
|
||||
@@ -1,49 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)search.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/* Backward compatibility to hsearch interface. */
|
||||
typedef struct entry {
|
||||
char *key;
|
||||
char *data;
|
||||
} ENTRY;
|
||||
|
||||
typedef enum {
|
||||
FIND, ENTER
|
||||
} ACTION;
|
||||
|
||||
int hcreate (unsigned int);
|
||||
void hdestroy (void);
|
||||
ENTRY *hsearch (ENTRY, ACTION);
|
||||
@@ -1,413 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)db.h 8.7 (Berkeley) 6/16/94
|
||||
*/
|
||||
|
||||
#ifndef _DB_H_
|
||||
#define _DB_H_
|
||||
|
||||
|
||||
#ifdef WINCE
|
||||
#define off_t long
|
||||
#endif
|
||||
|
||||
#ifndef macintosh
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include "prtypes.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef __DBINTERFACE_PRIVATE
|
||||
|
||||
#ifdef HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#else
|
||||
#include "cdefs.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_BYTEORDER_H
|
||||
#include <sys/byteorder.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux) || defined(__BEOS__)
|
||||
#include <endian.h>
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER __BYTE_ORDER
|
||||
#define BIG_ENDIAN __BIG_ENDIAN
|
||||
#define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif /* __linux */
|
||||
|
||||
#ifdef __sgi
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
|
||||
|
||||
#ifndef __SVR4
|
||||
/* compat.h is only in 4.1.3 machines. - dp */
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
/* XXX - dp
|
||||
* Need to find a general way of defining endian-ness in SunOS 5.3
|
||||
* SunOS 5.4 defines _BIG_ENDIAN and _LITTLE_ENDIAN
|
||||
* SunOS 5.3 does nothing like this.
|
||||
*/
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
|
||||
#if defined(_BIG_ENDIAN)
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#elif defined(_LITTLE_ENDIAN)
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#elif !defined(__SVR4)
|
||||
/* 4.1.3 is always BIG_ENDIAN as it was released only on sparc platforms. */
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#elif !defined(vax) && !defined(ntohl) && !defined(lint) && !defined(i386)
|
||||
/* 5.3 big endian. Copied this above line from sys/byteorder.h */
|
||||
/* Now we are in a 5.3 SunOS rather non 5.4 or above SunOS */
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif /* !BYTE_ORDER */
|
||||
#endif /* __sun */
|
||||
|
||||
#if defined(__hpux) || defined(__hppa)
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
|
||||
#endif
|
||||
|
||||
#if defined(AIXV3) || defined(AIX)
|
||||
/* BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN are all defined here */
|
||||
#include <sys/machine.h>
|
||||
#endif
|
||||
|
||||
/* Digital Unix */
|
||||
#ifdef __osf__
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef __alpha
|
||||
#ifndef WIN32
|
||||
#else
|
||||
/* Alpha NT */
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NCR
|
||||
#include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef __QNX__
|
||||
#ifdef __QNXNTO__
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SNI
|
||||
/* #include <sys/hetero.h> */
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#ifdef BYTE_ORDER
|
||||
#undef BYTE_ORDER
|
||||
#endif
|
||||
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax, all NT risc */
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#ifdef macintosh
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif /* __DBINTERFACE_PRIVATE */
|
||||
|
||||
#ifdef SCO
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#if defined(_WINDOWS) || defined(XP_OS2)
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
|
||||
#ifndef XP_OS2
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
|
||||
|
||||
#ifndef STDERR_FILENO
|
||||
#define STDIN_FILENO 0 /* ANSI C #defines */
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */
|
||||
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef macintosh
|
||||
#include <stdio.h>
|
||||
#include "xp_mcom.h"
|
||||
#define O_ACCMODE 3 /* Mask for file access modes */
|
||||
#define EFTYPE 2000
|
||||
PR_BEGIN_EXTERN_C
|
||||
int mkstemp(const char *path);
|
||||
PR_END_EXTERN_C
|
||||
#endif /* MACINTOSH */
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(macintosh)
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/* define EFTYPE since most don't */
|
||||
#ifndef EFTYPE
|
||||
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
|
||||
#endif
|
||||
|
||||
#define RET_ERROR -1 /* Return values. */
|
||||
#define RET_SUCCESS 0
|
||||
#define RET_SPECIAL 1
|
||||
|
||||
#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
|
||||
|
||||
#ifndef __sgi
|
||||
typedef uint32 pgno_t;
|
||||
#endif
|
||||
|
||||
#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
|
||||
typedef uint16 indx_t;
|
||||
#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
|
||||
typedef uint32 recno_t;
|
||||
|
||||
/* Key/data structure -- a Data-Base Thang. */
|
||||
typedef struct {
|
||||
void *data; /* data */
|
||||
size_t size; /* data length */
|
||||
} DBT;
|
||||
|
||||
/* Routine flags. */
|
||||
#define R_CURSOR 1 /* del, put, seq */
|
||||
#define __R_UNUSED 2 /* UNUSED */
|
||||
#define R_FIRST 3 /* seq */
|
||||
#define R_IAFTER 4 /* put (RECNO) */
|
||||
#define R_IBEFORE 5 /* put (RECNO) */
|
||||
#define R_LAST 6 /* seq (BTREE, RECNO) */
|
||||
#define R_NEXT 7 /* seq */
|
||||
#define R_NOOVERWRITE 8 /* put */
|
||||
#define R_PREV 9 /* seq (BTREE, RECNO) */
|
||||
#define R_SETCURSOR 10 /* put (RECNO) */
|
||||
#define R_RECNOSYNC 11 /* sync (RECNO) */
|
||||
|
||||
typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
|
||||
|
||||
typedef enum { LockOutDatabase, UnlockDatabase } DBLockFlagEnum;
|
||||
|
||||
/*
|
||||
* !!!
|
||||
* The following flags are included in the dbopen(3) call as part of the
|
||||
* open(2) flags. In order to avoid conflicts with the open flags, start
|
||||
* at the top of the 16 or 32-bit number space and work our way down. If
|
||||
* the open flags were significantly expanded in the future, it could be
|
||||
* a problem. Wish I'd left another flags word in the dbopen call.
|
||||
*
|
||||
* !!!
|
||||
* None of this stuff is implemented yet. The only reason that it's here
|
||||
* is so that the access methods can skip copying the key/data pair when
|
||||
* the DB_LOCK flag isn't set.
|
||||
*/
|
||||
#if UINT_MAX > 65535
|
||||
#define DB_LOCK 0x20000000 /* Do locking. */
|
||||
#define DB_SHMEM 0x40000000 /* Use shared memory. */
|
||||
#define DB_TXN 0x80000000 /* Do transactions. */
|
||||
#else
|
||||
#define DB_LOCK 0x2000 /* Do locking. */
|
||||
#define DB_SHMEM 0x4000 /* Use shared memory. */
|
||||
#define DB_TXN 0x8000 /* Do transactions. */
|
||||
#endif
|
||||
|
||||
/* Access method description structure. */
|
||||
typedef struct __db {
|
||||
DBTYPE type; /* Underlying db type. */
|
||||
int (*close) (struct __db *);
|
||||
int (*del) (const struct __db *, const DBT *, uint);
|
||||
int (*get) (const struct __db *, const DBT *, DBT *, uint);
|
||||
int (*put) (const struct __db *, DBT *, const DBT *, uint);
|
||||
int (*seq) (const struct __db *, DBT *, DBT *, uint);
|
||||
int (*sync) (const struct __db *, uint);
|
||||
void *internal; /* Access method private. */
|
||||
int (*fd) (const struct __db *);
|
||||
} DB;
|
||||
|
||||
#define BTREEMAGIC 0x053162
|
||||
#define BTREEVERSION 3
|
||||
|
||||
/* Structure used to pass parameters to the btree routines. */
|
||||
typedef struct {
|
||||
#define R_DUP 0x01 /* duplicate keys */
|
||||
uint32 flags;
|
||||
uint cachesize; /* bytes to cache */
|
||||
int maxkeypage; /* maximum keys per page */
|
||||
int minkeypage; /* minimum keys per page */
|
||||
uint psize; /* page size */
|
||||
int (*compare) /* comparison function */
|
||||
(const DBT *, const DBT *);
|
||||
size_t (*prefix) /* prefix function */
|
||||
(const DBT *, const DBT *);
|
||||
int lorder; /* byte order */
|
||||
} BTREEINFO;
|
||||
|
||||
#define HASHMAGIC 0x061561
|
||||
#define HASHVERSION 2
|
||||
|
||||
/* Structure used to pass parameters to the hashing routines. */
|
||||
typedef struct {
|
||||
uint bsize; /* bucket size */
|
||||
uint ffactor; /* fill factor */
|
||||
uint nelem; /* number of elements */
|
||||
uint cachesize; /* bytes to cache */
|
||||
uint32 /* hash function */
|
||||
(*hash) (const void *, size_t);
|
||||
int lorder; /* byte order */
|
||||
} HASHINFO;
|
||||
|
||||
/* Structure used to pass parameters to the record routines. */
|
||||
typedef struct {
|
||||
#define R_FIXEDLEN 0x01 /* fixed-length records */
|
||||
#define R_NOKEY 0x02 /* key not required */
|
||||
#define R_SNAPSHOT 0x04 /* snapshot the input */
|
||||
uint32 flags;
|
||||
uint cachesize; /* bytes to cache */
|
||||
uint psize; /* page size */
|
||||
int lorder; /* byte order */
|
||||
size_t reclen; /* record length (fixed-length records) */
|
||||
uint8 bval; /* delimiting byte (variable-length records */
|
||||
char *bfname; /* btree file name */
|
||||
} RECNOINFO;
|
||||
|
||||
#ifdef __DBINTERFACE_PRIVATE
|
||||
/*
|
||||
* Little endian <==> big endian 32-bit swap macros.
|
||||
* M_32_SWAP swap a memory location
|
||||
* P_32_SWAP swap a referenced memory location
|
||||
* P_32_COPY swap from one location to another
|
||||
*/
|
||||
#define M_32_SWAP(a) { \
|
||||
uint32 _tmp = a; \
|
||||
((char *)&a)[0] = ((char *)&_tmp)[3]; \
|
||||
((char *)&a)[1] = ((char *)&_tmp)[2]; \
|
||||
((char *)&a)[2] = ((char *)&_tmp)[1]; \
|
||||
((char *)&a)[3] = ((char *)&_tmp)[0]; \
|
||||
}
|
||||
#define P_32_SWAP(a) { \
|
||||
uint32 _tmp = *(uint32 *)a; \
|
||||
((char *)a)[0] = ((char *)&_tmp)[3]; \
|
||||
((char *)a)[1] = ((char *)&_tmp)[2]; \
|
||||
((char *)a)[2] = ((char *)&_tmp)[1]; \
|
||||
((char *)a)[3] = ((char *)&_tmp)[0]; \
|
||||
}
|
||||
#define P_32_COPY(a, b) { \
|
||||
((char *)&(b))[0] = ((char *)&(a))[3]; \
|
||||
((char *)&(b))[1] = ((char *)&(a))[2]; \
|
||||
((char *)&(b))[2] = ((char *)&(a))[1]; \
|
||||
((char *)&(b))[3] = ((char *)&(a))[0]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Little endian <==> big endian 16-bit swap macros.
|
||||
* M_16_SWAP swap a memory location
|
||||
* P_16_SWAP swap a referenced memory location
|
||||
* P_16_COPY swap from one location to another
|
||||
*/
|
||||
#define M_16_SWAP(a) { \
|
||||
uint16 _tmp = a; \
|
||||
((char *)&a)[0] = ((char *)&_tmp)[1]; \
|
||||
((char *)&a)[1] = ((char *)&_tmp)[0]; \
|
||||
}
|
||||
#define P_16_SWAP(a) { \
|
||||
uint16 _tmp = *(uint16 *)a; \
|
||||
((char *)a)[0] = ((char *)&_tmp)[1]; \
|
||||
((char *)a)[1] = ((char *)&_tmp)[0]; \
|
||||
}
|
||||
#define P_16_COPY(a, b) { \
|
||||
((char *)&(b))[0] = ((char *)&(a))[1]; \
|
||||
((char *)&(b))[1] = ((char *)&(a))[0]; \
|
||||
}
|
||||
#endif
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
extern DB *
|
||||
dbopen (const char *, int, int, DBTYPE, const void *);
|
||||
|
||||
/* set or unset a global lock flag to disable the
|
||||
* opening of any DBM file
|
||||
*/
|
||||
void dbSetOrClearDBLock(DBLockFlagEnum type);
|
||||
|
||||
#ifdef __DBINTERFACE_PRIVATE
|
||||
DB *__bt_open (const char *, int, int, const BTREEINFO *, int);
|
||||
DB *__hash_open (const char *, int, int, const HASHINFO *, int);
|
||||
DB *__rec_open (const char *, int, int, const RECNOINFO *, int);
|
||||
void __dbpanic (DB *dbp);
|
||||
#endif
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* !_DB_H_ */
|
||||
@@ -1,97 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mpool.h 8.2 (Berkeley) 7/14/94
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/*
|
||||
* The memory pool scheme is a simple one. Each in-memory page is referenced
|
||||
* by a bucket which is threaded in up to two of three ways. All active pages
|
||||
* are threaded on a hash chain (hashed by page number) and an lru chain.
|
||||
* Inactive pages are threaded on a free chain. Each reference to a memory
|
||||
* pool is handed an opaque MPOOL cookie which stores all of this information.
|
||||
*/
|
||||
#define HASHSIZE 128
|
||||
#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE)
|
||||
|
||||
/* The BKT structures are the elements of the queues. */
|
||||
typedef struct _bkt {
|
||||
CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */
|
||||
CIRCLEQ_ENTRY(_bkt) q; /* lru queue */
|
||||
void *page; /* page */
|
||||
pgno_t pgno; /* page number */
|
||||
|
||||
#define MPOOL_DIRTY 0x01 /* page needs to be written */
|
||||
#define MPOOL_PINNED 0x02 /* page is pinned into memory */
|
||||
uint8 flags; /* flags */
|
||||
} BKT;
|
||||
|
||||
typedef struct MPOOL {
|
||||
CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */
|
||||
/* hash queue array */
|
||||
CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
|
||||
pgno_t curcache; /* current number of cached pages */
|
||||
pgno_t maxcache; /* max number of cached pages */
|
||||
pgno_t npages; /* number of pages in the file */
|
||||
uint32 pagesize; /* file page size */
|
||||
int fd; /* file descriptor */
|
||||
/* page in conversion routine */
|
||||
void (*pgin) (void *, pgno_t, void *);
|
||||
/* page out conversion routine */
|
||||
void (*pgout) (void *, pgno_t, void *);
|
||||
void *pgcookie; /* cookie for page in/out routines */
|
||||
#ifdef STATISTICS
|
||||
uint32 cachehit;
|
||||
uint32 cachemiss;
|
||||
uint32 pagealloc;
|
||||
uint32 pageflush;
|
||||
uint32 pageget;
|
||||
uint32 pagenew;
|
||||
uint32 pageput;
|
||||
uint32 pageread;
|
||||
uint32 pagewrite;
|
||||
#endif
|
||||
} MPOOL;
|
||||
|
||||
__BEGIN_DECLS
|
||||
MPOOL *mpool_open (void *, int, pgno_t, pgno_t);
|
||||
void mpool_filter (MPOOL *, void (*)(void *, pgno_t, void *),
|
||||
void (*)(void *, pgno_t, void *), void *);
|
||||
void *mpool_new (MPOOL *, pgno_t *);
|
||||
void *mpool_get (MPOOL *, pgno_t, uint);
|
||||
int mpool_put (MPOOL *, void *, uint);
|
||||
int mpool_sync (MPOOL *);
|
||||
int mpool_close (MPOOL *);
|
||||
#ifdef STATISTICS
|
||||
void mpool_stat (MPOOL *);
|
||||
#endif
|
||||
__END_DECLS
|
||||
@@ -1,230 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)compat.h 8.13 (Berkeley) 2/21/94
|
||||
*/
|
||||
|
||||
#ifndef _COMPAT_H_
|
||||
#define _COMPAT_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* If your system doesn't typedef u_long, u_short, or u_char, change
|
||||
* the 0 to a 1.
|
||||
*/
|
||||
#if 0
|
||||
typedef unsigned char u_char; /* 4.[34]BSD names. */
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
typedef unsigned short u_short;
|
||||
#endif
|
||||
|
||||
/* If your system doesn't typedef size_t, change the 0 to a 1. */
|
||||
#if 0
|
||||
typedef unsigned int size_t; /* POSIX, 4.[34]BSD names. */
|
||||
#endif
|
||||
|
||||
/* If your system doesn't typedef ssize_t, change the 0 to a 1. */
|
||||
#if 0
|
||||
typedef int ssize_t; /* POSIX names. */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If your system doesn't have the POSIX type for a signal mask,
|
||||
* change the 0 to a 1.
|
||||
*/
|
||||
#if 0 /* POSIX 1003.1 signal mask type. */
|
||||
typedef unsigned int sigset_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If your system's vsprintf returns a char *, not an int,
|
||||
* change the 0 to a 1.
|
||||
*/
|
||||
#if defined (__sun) && !defined(__SVR4) /* SUNOS */
|
||||
#define VSPRINTF_CHARSTAR
|
||||
#endif
|
||||
/*
|
||||
* If you don't have POSIX 1003.1 signals, the signal code surrounding the
|
||||
* temporary file creation is intended to block all of the possible signals
|
||||
* long enough to create the file and unlink it. All of this stuff is
|
||||
* intended to use old-style BSD calls to fake POSIX 1003.1 calls.
|
||||
*/
|
||||
#ifdef NO_POSIX_SIGNALS
|
||||
#define sigemptyset(set) (*(set) = 0)
|
||||
#define sigfillset(set) (*(set) = ~(sigset_t)0, 0)
|
||||
#define sigaddset(set,signo) (*(set) |= sigmask(signo), 0)
|
||||
#define sigdelset(set,signo) (*(set) &= ~sigmask(signo), 0)
|
||||
#define sigismember(set,signo) ((*(set) & sigmask(signo)) != 0)
|
||||
|
||||
#define SIG_BLOCK 1
|
||||
#define SIG_UNBLOCK 2
|
||||
#define SIG_SETMASK 3
|
||||
|
||||
static int __sigtemp; /* For the use of sigprocmask */
|
||||
|
||||
/* Repeated test of oset != NULL is to avoid "*0". */
|
||||
#define sigprocmask(how, set, oset) \
|
||||
((__sigtemp = \
|
||||
(((how) == SIG_BLOCK) ? \
|
||||
sigblock(0) | *(set) : \
|
||||
(((how) == SIG_UNBLOCK) ? \
|
||||
sigblock(0) & ~(*(set)) : \
|
||||
((how) == SIG_SETMASK ? \
|
||||
*(set) : sigblock(0))))), \
|
||||
((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) : \
|
||||
sigsetmask(__sigtemp)), 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If your system doesn't have an include file with the appropriate
|
||||
* byte order set, make sure you specify the correct one.
|
||||
*/
|
||||
#ifndef BYTE_ORDER
|
||||
#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
|
||||
#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
|
||||
#define BYTE_ORDER BIG_ENDIAN /* Set for your system. */
|
||||
#endif
|
||||
|
||||
#if defined(SYSV) || defined(SYSTEM5) || defined(__sun)
|
||||
#define index(a, b) strchr(a, b)
|
||||
#define rindex(a, b) strrchr(a, b)
|
||||
#define bzero(a, b) memset(a, 0, b)
|
||||
#define bcmp(a, b, n) memcmp(a, b, n)
|
||||
#define bcopy(a, b, n) memmove(b, a, n)
|
||||
#endif
|
||||
|
||||
#if defined(BSD) || defined(BSD4_3)
|
||||
#define strchr(a, b) index(a, b)
|
||||
#define strrchr(a, b) rindex(a, b)
|
||||
#define memcmp(a, b, n) bcmp(a, b, n)
|
||||
#define memmove(a, b, n) bcopy(b, a, n)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 32-bit machine. The db routines are theoretically independent of
|
||||
* the size of u_shorts and u_longs, but I don't know that anyone has
|
||||
* ever actually tried it. At a minimum, change the following #define's
|
||||
* if you are trying to compile on a different type of system.
|
||||
*/
|
||||
#ifndef USHRT_MAX
|
||||
#define USHRT_MAX 0xFFFF
|
||||
#define ULONG_MAX 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */
|
||||
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 RE limit. */
|
||||
#define _POSIX2_RE_DUP_MAX 255
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If you can't provide lock values in the open(2) call. Note, this
|
||||
* allows races to happen.
|
||||
*/
|
||||
#ifndef O_EXLOCK /* 4.4BSD extension. */
|
||||
#define O_EXLOCK 0
|
||||
#endif
|
||||
|
||||
#ifndef O_SHLOCK /* 4.4BSD extension. */
|
||||
#define O_SHLOCK 0
|
||||
#endif
|
||||
|
||||
#ifndef EFTYPE
|
||||
#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
|
||||
#endif
|
||||
|
||||
#ifndef WCOREDUMP /* 4.4BSD extension */
|
||||
#define WCOREDUMP(a) 0
|
||||
#endif
|
||||
|
||||
#ifndef STDERR_FILENO
|
||||
#define STDIN_FILENO 0 /* ANSI C #defines */
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_SET 0 /* POSIX 1003.1 seek values */
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */
|
||||
#define _POSIX_VDISABLE 0 /* Some systems used 0. */
|
||||
#endif
|
||||
|
||||
#ifndef TCSASOFT /* 4.4BSD extension. */
|
||||
#define TCSASOFT 0
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX2_RE_DUP_MAX /* POSIX 1003.2 values. */
|
||||
#define _POSIX2_RE_DUP_MAX 255
|
||||
#endif
|
||||
|
||||
#ifndef NULL /* ANSI C #defines NULL everywhere. */
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef MAX /* Usually found in <sys/param.h>. */
|
||||
#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a))
|
||||
#endif
|
||||
#ifndef MIN /* Usually found in <sys/param.h>. */
|
||||
#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
|
||||
#endif
|
||||
|
||||
/* Default file permissions. */
|
||||
#ifndef DEFFILEMODE /* 4.4BSD extension. */
|
||||
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||
#endif
|
||||
|
||||
#ifndef __sun
|
||||
#ifndef S_ISDIR /* POSIX 1003.1 file type tests. */
|
||||
#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */
|
||||
#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */
|
||||
#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */
|
||||
#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */
|
||||
#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */
|
||||
#endif
|
||||
#ifndef S_ISLNK /* BSD POSIX 1003.1 extensions */
|
||||
#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */
|
||||
#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */
|
||||
#endif
|
||||
#endif /* __sun */
|
||||
|
||||
/* The type of a va_list. */
|
||||
#ifndef _BSD_VA_LIST_ /* 4.4BSD #define. */
|
||||
#define _BSD_VA_LIST_ char *
|
||||
#endif
|
||||
|
||||
#endif /* !_COMPAT_H_ */
|
||||
@@ -1,94 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)page.h 8.2 (Berkeley) 5/31/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definitions for hashing page file format.
|
||||
*/
|
||||
|
||||
/*
|
||||
* routines dealing with a data page
|
||||
*
|
||||
* page format:
|
||||
* +------------------------------+
|
||||
* p | n | keyoff | datoff | keyoff |
|
||||
* +------------+--------+--------+
|
||||
* | datoff | free | ptr | --> |
|
||||
* +--------+---------------------+
|
||||
* | F R E E A R E A |
|
||||
* +--------------+---------------+
|
||||
* | <---- - - - | data |
|
||||
* +--------+-----+----+----------+
|
||||
* | key | data | key |
|
||||
* +--------+----------+----------+
|
||||
*
|
||||
* Pointer to the free space is always: p[p[0] + 2]
|
||||
* Amount of free space on the page is: p[p[0] + 1]
|
||||
*/
|
||||
|
||||
/*
|
||||
* How many bytes required for this pair?
|
||||
* 2 shorts in the table at the top of the page + room for the
|
||||
* key and room for the data
|
||||
*
|
||||
* We prohibit entering a pair on a page unless there is also room to append
|
||||
* an overflow page. The reason for this it that you can get in a situation
|
||||
* where a single key/data pair fits on a page, but you can't append an
|
||||
* overflow page and later you'd have to split the key/data and handle like
|
||||
* a big pair.
|
||||
* You might as well do this up front.
|
||||
*/
|
||||
#ifndef PAGE_H
|
||||
#define PAGE_H
|
||||
|
||||
#define PAIRSIZE(K,D) (2*sizeof(uint16) + (K)->size + (D)->size)
|
||||
#define BIGOVERHEAD (4*sizeof(uint16))
|
||||
#define KEYSIZE(K) (4*sizeof(uint16) + (K)->size);
|
||||
#define OVFLSIZE (2*sizeof(uint16))
|
||||
#define FREESPACE(P) ((P)[(P)[0]+1])
|
||||
#define OFFSET(P) ((P)[(P)[0]+2])
|
||||
#define PAIRFITS(P,K,D) \
|
||||
(((P)[2] >= REAL_KEY) && \
|
||||
(PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
|
||||
#define PAGE_META(N) (((N)+3) * sizeof(uint16))
|
||||
|
||||
typedef struct {
|
||||
BUFHEAD *newp;
|
||||
BUFHEAD *oldp;
|
||||
BUFHEAD *nextp;
|
||||
uint16 next_addr;
|
||||
} SPLIT_RETURN;
|
||||
#endif
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.3 (Berkeley) 12/13/93
|
||||
*/
|
||||
|
||||
#ifndef _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines three types of data structures: lists, tail queues,
|
||||
* and circular queues.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list after
|
||||
* an existing element or at the head of the list. A list may only be
|
||||
* traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A tail queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define LIST_INIT(head) { \
|
||||
(head)->lh_first = NULL; \
|
||||
}
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
}
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
}
|
||||
|
||||
#define LIST_REMOVE(elm, field) { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_INIT(head) { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_last = &(head)->tqh_first; \
|
||||
}
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||
}
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
}
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||
}
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue definitions.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_INIT(head) { \
|
||||
(head)->cqh_first = (void *)(head); \
|
||||
(head)->cqh_last = (void *)(head); \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \
|
||||
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
||||
(elm)->field.cqe_prev = (listelm); \
|
||||
if ((listelm)->field.cqe_next == (void *)(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
||||
(listelm)->field.cqe_next = (elm); \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \
|
||||
(elm)->field.cqe_next = (listelm); \
|
||||
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
||||
if ((listelm)->field.cqe_prev == (void *)(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
||||
(listelm)->field.cqe_prev = (elm); \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \
|
||||
(elm)->field.cqe_next = (head)->cqh_first; \
|
||||
(elm)->field.cqe_prev = (void *)(head); \
|
||||
if ((head)->cqh_last == (void *)(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(head)->cqh_first->field.cqe_prev = (elm); \
|
||||
(head)->cqh_first = (elm); \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \
|
||||
(elm)->field.cqe_next = (void *)(head); \
|
||||
(elm)->field.cqe_prev = (head)->cqh_last; \
|
||||
if ((head)->cqh_first == (void *)(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(head)->cqh_last->field.cqe_next = (elm); \
|
||||
(head)->cqh_last = (elm); \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) { \
|
||||
if ((elm)->field.cqe_next == (void *)(head)) \
|
||||
(head)->cqh_last = (elm)->field.cqe_prev; \
|
||||
else \
|
||||
(elm)->field.cqe_next->field.cqe_prev = \
|
||||
(elm)->field.cqe_prev; \
|
||||
if ((elm)->field.cqe_prev == (void *)(head)) \
|
||||
(head)->cqh_first = (elm)->field.cqe_next; \
|
||||
else \
|
||||
(elm)->field.cqe_prev->field.cqe_next = \
|
||||
(elm)->field.cqe_next; \
|
||||
}
|
||||
#endif /* !_QUEUE_H_ */
|
||||
@@ -1,49 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)search.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/* Backward compatibility to hsearch interface. */
|
||||
typedef struct entry {
|
||||
char *key;
|
||||
char *data;
|
||||
} ENTRY;
|
||||
|
||||
typedef enum {
|
||||
FIND, ENTER
|
||||
} ACTION;
|
||||
|
||||
int hcreate (unsigned int);
|
||||
void hdestroy (void);
|
||||
ENTRY *hsearch (ENTRY, ACTION);
|
||||
@@ -1,112 +0,0 @@
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Stuff to fake unix file I/O on windows boxes
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef WINFILE_H
|
||||
#define WINFILE_H
|
||||
|
||||
#ifdef _WINDOWS
|
||||
/* hacked out of <dirent.h> on an SGI */
|
||||
#if defined(XP_WIN32) || defined(_WIN32)
|
||||
/* 32-bit stuff here */
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#else
|
||||
#include <sys\types.h>
|
||||
#include <sys\stat.h>
|
||||
#endif
|
||||
|
||||
typedef struct DIR_Struct {
|
||||
void * directoryPtr;
|
||||
WIN32_FIND_DATA data;
|
||||
} DIR;
|
||||
|
||||
#define _ST_FSTYPSZ 16
|
||||
|
||||
#if !defined(__BORLANDC__) && !defined(__GNUC__)
|
||||
typedef unsigned long mode_t;
|
||||
typedef long uid_t;
|
||||
typedef long gid_t;
|
||||
|
||||
#ifdef WINCE
|
||||
typedef long ino_t;
|
||||
#else
|
||||
typedef long off_t;
|
||||
#endif
|
||||
|
||||
typedef unsigned long nlink_t;
|
||||
#endif
|
||||
|
||||
typedef struct timestruc {
|
||||
time_t tv_sec; /* seconds */
|
||||
long tv_nsec; /* and nanoseconds */
|
||||
} timestruc_t;
|
||||
|
||||
|
||||
struct dirent { /* data from readdir() */
|
||||
ino_t d_ino; /* inode number of entry */
|
||||
off_t d_off; /* offset of disk direntory entry */
|
||||
unsigned short d_reclen; /* length of this record */
|
||||
char d_name[_MAX_FNAME]; /* name of file */
|
||||
};
|
||||
|
||||
#if !defined(__BORLANDC__) && !defined (__GNUC__)
|
||||
#define S_ISDIR(s) ((s) & _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#else /* _WIN32 */
|
||||
/* 16-bit windows stuff */
|
||||
|
||||
#include <sys\types.h>
|
||||
#include <sys\stat.h>
|
||||
#include <dos.h>
|
||||
|
||||
|
||||
|
||||
/* Getting cocky to support multiple file systems */
|
||||
typedef struct dirStruct_tag {
|
||||
struct _find_t file_data;
|
||||
char c_checkdrive;
|
||||
} dirStruct;
|
||||
|
||||
typedef struct DIR_Struct {
|
||||
void * directoryPtr;
|
||||
dirStruct data;
|
||||
} DIR;
|
||||
|
||||
#define _ST_FSTYPSZ 16
|
||||
typedef unsigned long mode_t;
|
||||
typedef long uid_t;
|
||||
typedef long gid_t;
|
||||
typedef long off_t;
|
||||
typedef unsigned long nlink_t;
|
||||
|
||||
typedef struct timestruc {
|
||||
time_t tv_sec; /* seconds */
|
||||
long tv_nsec; /* and nanoseconds */
|
||||
} timestruc_t;
|
||||
|
||||
struct dirent { /* data from readdir() */
|
||||
ino_t d_ino; /* inode number of entry */
|
||||
off_t d_off; /* offset of disk direntory entry */
|
||||
unsigned short d_reclen; /* length of this record */
|
||||
#ifdef XP_WIN32
|
||||
char d_name[_MAX_FNAME]; /* name of file */
|
||||
#else
|
||||
char d_name[20]; /* name of file */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define S_ISDIR(s) ((s) & _S_IFDIR)
|
||||
|
||||
#endif /* 16-bit windows */
|
||||
|
||||
#define CONST const
|
||||
|
||||
#endif /* _WINDOWS */
|
||||
|
||||
#endif /* WINFILE_H */
|
||||
@@ -1,95 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = mozdbm_s
|
||||
LIB_IS_C_ONLY = 1
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
LIBRARY_NAME = dbm$(MOZ_BITS)
|
||||
endif
|
||||
|
||||
CSRCS = \
|
||||
db.c \
|
||||
h_bigkey.c \
|
||||
h_func.c \
|
||||
h_log2.c \
|
||||
h_page.c \
|
||||
hash.c \
|
||||
hash_buf.c \
|
||||
hsearch.c \
|
||||
mktemp.c \
|
||||
ndbm.c \
|
||||
strerror.c \
|
||||
nsres.c \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
CSRCS += memmove.c snprintf.c
|
||||
else
|
||||
ifeq (,$(filter -DHAVE_MEMMOVE=1,$(ACDEFINES)))
|
||||
CSRCS += memmove.c
|
||||
endif
|
||||
|
||||
ifeq (,$(filter -DHAVE_SNPRINTF=1,$(ACDEFINES)))
|
||||
CSRCS += snprintf.c
|
||||
endif
|
||||
endif # WINNT
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../include
|
||||
|
||||
FORCE_STATIC_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -DMEMMOVE -D__DBINTERFACE_PRIVATE $(SECURITY_FLAG)
|
||||
|
||||
ifeq ($(OS_ARCH),WINCE)
|
||||
DEFINES += -D__STDC__ -DDBM_REOPEN_ON_FLUSH
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),AIX)
|
||||
OS_LIBS += -lc_r
|
||||
endif
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Makefile to build the cert library
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
!ifndef MOZ_DEBUG
|
||||
OPTIMIZER=-Os -UDEBUG -DNDEBUG
|
||||
!endif
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Specify the depth of the current directory relative to the
|
||||
#// root of NS
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DEPTH= ..\..
|
||||
|
||||
!ifndef MAKE_OBJ_TYPE
|
||||
MAKE_OBJ_TYPE=EXE
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
LIBNAME=dbm$(MOZ_BITS)
|
||||
PDBFILE=$(LIBNAME).pdb
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define the files necessary to build the target (ie. OBJS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
OBJS= \
|
||||
.\$(OBJDIR)\db.obj \
|
||||
.\$(OBJDIR)\h_bigkey.obj \
|
||||
.\$(OBJDIR)\h_func.obj \
|
||||
.\$(OBJDIR)\h_log2.obj \
|
||||
.\$(OBJDIR)\h_page.obj \
|
||||
.\$(OBJDIR)\hash.obj \
|
||||
.\$(OBJDIR)\hash_buf.obj \
|
||||
.\$(OBJDIR)\hsearch.obj \
|
||||
.\$(OBJDIR)\memmove.obj \
|
||||
.\$(OBJDIR)\mktemp.obj \
|
||||
.\$(OBJDIR)\ndbm.obj \
|
||||
.\$(OBJDIR)\snprintf.obj \
|
||||
.\$(OBJDIR)\strerror.obj \
|
||||
.\$(OBJDIR)\nsres.obj \
|
||||
$(NULL)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
|
||||
#// (these must be defined before the common makefiles are included)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
LIBRARY = .\$(OBJDIR)\$(LIBNAME).lib
|
||||
LINCS = -I..\include
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Include the common makefile rules
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
CFLAGS = $(CFLAGS) -DMOZILLA_CLIENT -D__DBINTERFACE_PRIVATE
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#ifndef __DBINTERFACE_PRIVATE
|
||||
#define __DBINTERFACE_PRIVATE
|
||||
#endif
|
||||
#ifdef macintosh
|
||||
#include <unix.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mcom_db.h"
|
||||
|
||||
/* a global flag that locks closed all databases */
|
||||
int all_databases_locked_closed = 0;
|
||||
|
||||
/* set or unset a global lock flag to disable the
|
||||
* opening of any DBM file
|
||||
*/
|
||||
void
|
||||
dbSetOrClearDBLock(DBLockFlagEnum type)
|
||||
{
|
||||
if(type == LockOutDatabase)
|
||||
all_databases_locked_closed = 1;
|
||||
else
|
||||
all_databases_locked_closed = 0;
|
||||
}
|
||||
|
||||
DB *
|
||||
dbopen(const char *fname, int flags,int mode, DBTYPE type, const void *openinfo)
|
||||
{
|
||||
|
||||
/* lock out all file databases. Let in-memory databases through
|
||||
*/
|
||||
if(all_databases_locked_closed && fname)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
|
||||
|
||||
|
||||
#if 0 /* most systems don't have EXLOCK and SHLOCK */
|
||||
#define USE_OPEN_FLAGS \
|
||||
(O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \
|
||||
O_RDWR | O_SHLOCK | O_TRUNC)
|
||||
#else
|
||||
#define USE_OPEN_FLAGS \
|
||||
(O_CREAT | O_EXCL | O_RDONLY | \
|
||||
O_RDWR | O_TRUNC)
|
||||
#endif
|
||||
|
||||
if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
|
||||
switch (type) {
|
||||
/* we don't need btree and recno right now */
|
||||
#if 0
|
||||
case DB_BTREE:
|
||||
return (__bt_open(fname, flags & USE_OPEN_FLAGS,
|
||||
mode, openinfo, flags & DB_FLAGS));
|
||||
case DB_RECNO:
|
||||
return (__rec_open(fname, flags & USE_OPEN_FLAGS,
|
||||
mode, openinfo, flags & DB_FLAGS));
|
||||
#endif
|
||||
|
||||
case DB_HASH:
|
||||
return (__hash_open(fname, flags & USE_OPEN_FLAGS,
|
||||
mode, (const HASHINFO *)openinfo, flags & DB_FLAGS));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
__dberr()
|
||||
{
|
||||
return (RET_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* __DBPANIC -- Stop.
|
||||
*
|
||||
* Parameters:
|
||||
* dbp: pointer to the DB structure.
|
||||
*/
|
||||
void
|
||||
__dbpanic(DB *dbp)
|
||||
{
|
||||
/* The only thing that can succeed is a close. */
|
||||
dbp->del = (int (*)(const struct __db *, const DBT *, uint))__dberr;
|
||||
dbp->fd = (int (*)(const struct __db *))__dberr;
|
||||
dbp->get = (int (*)(const struct __db *, const DBT *, DBT *, uint))__dberr;
|
||||
dbp->put = (int (*)(const struct __db *, DBT *, const DBT *, uint))__dberr;
|
||||
dbp->seq = (int (*)(const struct __db *, DBT *, DBT *, uint))__dberr;
|
||||
dbp->sync = (int (*)(const struct __db *, uint))__dberr;
|
||||
}
|
||||
@@ -1,709 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/*
|
||||
* PACKAGE: hash
|
||||
* DESCRIPTION:
|
||||
* Big key/data handling for the hashing package.
|
||||
*
|
||||
* ROUTINES:
|
||||
* External
|
||||
* __big_keydata
|
||||
* __big_split
|
||||
* __big_insert
|
||||
* __big_return
|
||||
* __big_delete
|
||||
* __find_last_page
|
||||
* Internal
|
||||
* collect_key
|
||||
* collect_data
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "mcom_db.h"
|
||||
#include "hash.h"
|
||||
#include "page.h"
|
||||
/* #include "extern.h" */
|
||||
|
||||
static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));
|
||||
static int collect_data __P((HTAB *, BUFHEAD *, int, int));
|
||||
|
||||
/*
|
||||
* Big_insert
|
||||
*
|
||||
* You need to do an insert and the key/data pair is too big
|
||||
*
|
||||
* Returns:
|
||||
* 0 ==> OK
|
||||
*-1 ==> ERROR
|
||||
*/
|
||||
extern int
|
||||
__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
|
||||
{
|
||||
register uint16 *p;
|
||||
uint key_size, n, val_size;
|
||||
uint16 space, move_bytes, off;
|
||||
char *cp, *key_data, *val_data;
|
||||
|
||||
cp = bufp->page; /* Character pointer of p. */
|
||||
p = (uint16 *)cp;
|
||||
|
||||
key_data = (char *)key->data;
|
||||
key_size = key->size;
|
||||
val_data = (char *)val->data;
|
||||
val_size = val->size;
|
||||
|
||||
/* First move the Key */
|
||||
for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
|
||||
space = FREESPACE(p) - BIGOVERHEAD) {
|
||||
move_bytes = PR_MIN(space, key_size);
|
||||
off = OFFSET(p) - move_bytes;
|
||||
memmove(cp + off, key_data, move_bytes);
|
||||
key_size -= move_bytes;
|
||||
key_data += move_bytes;
|
||||
n = p[0];
|
||||
p[++n] = off;
|
||||
p[0] = ++n;
|
||||
FREESPACE(p) = off - PAGE_META(n);
|
||||
OFFSET(p) = off;
|
||||
p[n] = PARTIAL_KEY;
|
||||
bufp = __add_ovflpage(hashp, bufp);
|
||||
if (!bufp)
|
||||
return (-1);
|
||||
n = p[0];
|
||||
if (!key_size) {
|
||||
if (FREESPACE(p)) {
|
||||
move_bytes = PR_MIN(FREESPACE(p), val_size);
|
||||
off = OFFSET(p) - move_bytes;
|
||||
p[n] = off;
|
||||
memmove(cp + off, val_data, move_bytes);
|
||||
val_data += move_bytes;
|
||||
val_size -= move_bytes;
|
||||
p[n - 2] = FULL_KEY_DATA;
|
||||
FREESPACE(p) = FREESPACE(p) - move_bytes;
|
||||
OFFSET(p) = off;
|
||||
} else
|
||||
p[n - 2] = FULL_KEY;
|
||||
}
|
||||
p = (uint16 *)bufp->page;
|
||||
cp = bufp->page;
|
||||
bufp->flags |= BUF_MOD;
|
||||
}
|
||||
|
||||
/* Now move the data */
|
||||
for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
|
||||
space = FREESPACE(p) - BIGOVERHEAD) {
|
||||
move_bytes = PR_MIN(space, val_size);
|
||||
/*
|
||||
* Here's the hack to make sure that if the data ends on the
|
||||
* same page as the key ends, FREESPACE is at least one.
|
||||
*/
|
||||
if (space == val_size && val_size == val->size)
|
||||
move_bytes--;
|
||||
off = OFFSET(p) - move_bytes;
|
||||
memmove(cp + off, val_data, move_bytes);
|
||||
val_size -= move_bytes;
|
||||
val_data += move_bytes;
|
||||
n = p[0];
|
||||
p[++n] = off;
|
||||
p[0] = ++n;
|
||||
FREESPACE(p) = off - PAGE_META(n);
|
||||
OFFSET(p) = off;
|
||||
if (val_size) {
|
||||
p[n] = FULL_KEY;
|
||||
bufp = __add_ovflpage(hashp, bufp);
|
||||
if (!bufp)
|
||||
return (-1);
|
||||
cp = bufp->page;
|
||||
p = (uint16 *)cp;
|
||||
} else
|
||||
p[n] = FULL_KEY_DATA;
|
||||
bufp->flags |= BUF_MOD;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when bufp's page contains a partial key (index should be 1)
|
||||
*
|
||||
* All pages in the big key/data pair except bufp are freed. We cannot
|
||||
* free bufp because the page pointing to it is lost and we can't get rid
|
||||
* of its pointer.
|
||||
*
|
||||
* Returns:
|
||||
* 0 => OK
|
||||
*-1 => ERROR
|
||||
*/
|
||||
extern int
|
||||
__big_delete(HTAB *hashp, BUFHEAD *bufp)
|
||||
{
|
||||
register BUFHEAD *last_bfp, *rbufp;
|
||||
uint16 *bp, pageno;
|
||||
int key_done, n;
|
||||
|
||||
rbufp = bufp;
|
||||
last_bfp = NULL;
|
||||
bp = (uint16 *)bufp->page;
|
||||
pageno = 0;
|
||||
key_done = 0;
|
||||
|
||||
while (!key_done || (bp[2] != FULL_KEY_DATA)) {
|
||||
if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
|
||||
key_done = 1;
|
||||
|
||||
/*
|
||||
* If there is freespace left on a FULL_KEY_DATA page, then
|
||||
* the data is short and fits entirely on this page, and this
|
||||
* is the last page.
|
||||
*/
|
||||
if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
|
||||
break;
|
||||
pageno = bp[bp[0] - 1];
|
||||
rbufp->flags |= BUF_MOD;
|
||||
rbufp = __get_buf(hashp, pageno, rbufp, 0);
|
||||
if (last_bfp)
|
||||
__free_ovflpage(hashp, last_bfp);
|
||||
last_bfp = rbufp;
|
||||
if (!rbufp)
|
||||
return (-1); /* Error. */
|
||||
bp = (uint16 *)rbufp->page;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here then rbufp points to the last page of the big
|
||||
* key/data pair. Bufp points to the first one -- it should now be
|
||||
* empty pointing to the next page after this pair. Can't free it
|
||||
* because we don't have the page pointing to it.
|
||||
*/
|
||||
|
||||
/* This is information from the last page of the pair. */
|
||||
n = bp[0];
|
||||
pageno = bp[n - 1];
|
||||
|
||||
/* Now, bp is the first page of the pair. */
|
||||
bp = (uint16 *)bufp->page;
|
||||
if (n > 2) {
|
||||
/* There is an overflow page. */
|
||||
bp[1] = pageno;
|
||||
bp[2] = OVFLPAGE;
|
||||
bufp->ovfl = rbufp->ovfl;
|
||||
} else
|
||||
/* This is the last page. */
|
||||
bufp->ovfl = NULL;
|
||||
n -= 2;
|
||||
bp[0] = n;
|
||||
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
|
||||
OFFSET(bp) = hashp->BSIZE - 1;
|
||||
|
||||
bufp->flags |= BUF_MOD;
|
||||
if (rbufp)
|
||||
__free_ovflpage(hashp, rbufp);
|
||||
if (last_bfp != rbufp)
|
||||
__free_ovflpage(hashp, last_bfp);
|
||||
|
||||
hashp->NKEYS--;
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Returns:
|
||||
* 0 = key not found
|
||||
* -1 = get next overflow page
|
||||
* -2 means key not found and this is big key/data
|
||||
* -3 error
|
||||
*/
|
||||
extern int
|
||||
__find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
|
||||
{
|
||||
register uint16 *bp;
|
||||
register char *p;
|
||||
int ksize;
|
||||
uint16 bytes;
|
||||
char *kkey;
|
||||
|
||||
bp = (uint16 *)bufp->page;
|
||||
p = bufp->page;
|
||||
ksize = size;
|
||||
kkey = key;
|
||||
|
||||
for (bytes = hashp->BSIZE - bp[ndx];
|
||||
bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
|
||||
bytes = hashp->BSIZE - bp[ndx]) {
|
||||
if (memcmp(p + bp[ndx], kkey, bytes))
|
||||
return (-2);
|
||||
kkey += bytes;
|
||||
ksize -= bytes;
|
||||
bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
|
||||
if (!bufp)
|
||||
return (-3);
|
||||
p = bufp->page;
|
||||
bp = (uint16 *)p;
|
||||
ndx = 1;
|
||||
}
|
||||
|
||||
if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
|
||||
#ifdef HASH_STATISTICS
|
||||
++hash_collisions;
|
||||
#endif
|
||||
return (-2);
|
||||
} else
|
||||
return (ndx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the buffer pointer of the first overflow page of a big pair,
|
||||
* find the end of the big pair
|
||||
*
|
||||
* This will set bpp to the buffer header of the last page of the big pair.
|
||||
* It will return the pageno of the overflow page following the last page
|
||||
* of the pair; 0 if there isn't any (i.e. big pair is the last key in the
|
||||
* bucket)
|
||||
*/
|
||||
extern uint16
|
||||
__find_last_page(HTAB *hashp, BUFHEAD **bpp)
|
||||
{
|
||||
BUFHEAD *bufp;
|
||||
uint16 *bp, pageno;
|
||||
uint n;
|
||||
|
||||
bufp = *bpp;
|
||||
bp = (uint16 *)bufp->page;
|
||||
for (;;) {
|
||||
n = bp[0];
|
||||
|
||||
/*
|
||||
* This is the last page if: the tag is FULL_KEY_DATA and
|
||||
* either only 2 entries OVFLPAGE marker is explicit there
|
||||
* is freespace on the page.
|
||||
*/
|
||||
if (bp[2] == FULL_KEY_DATA &&
|
||||
((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
|
||||
break;
|
||||
|
||||
/* LJM bound the size of n to reasonable limits
|
||||
*/
|
||||
if(n > hashp->BSIZE/sizeof(uint16))
|
||||
return(0);
|
||||
|
||||
pageno = bp[n - 1];
|
||||
bufp = __get_buf(hashp, pageno, bufp, 0);
|
||||
if (!bufp)
|
||||
return (0); /* Need to indicate an error! */
|
||||
bp = (uint16 *)bufp->page;
|
||||
}
|
||||
|
||||
*bpp = bufp;
|
||||
if (bp[0] > 2)
|
||||
return (bp[3]);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the data for the key/data pair that begins on this page at this
|
||||
* index (index should always be 1).
|
||||
*/
|
||||
extern int
|
||||
__big_return(
|
||||
HTAB *hashp,
|
||||
BUFHEAD *bufp,
|
||||
int ndx,
|
||||
DBT *val,
|
||||
int set_current)
|
||||
{
|
||||
BUFHEAD *save_p;
|
||||
uint16 *bp, len, off, save_addr;
|
||||
char *tp;
|
||||
int save_flags;
|
||||
|
||||
bp = (uint16 *)bufp->page;
|
||||
while (bp[ndx + 1] == PARTIAL_KEY) {
|
||||
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
|
||||
if (!bufp)
|
||||
return (-1);
|
||||
bp = (uint16 *)bufp->page;
|
||||
ndx = 1;
|
||||
}
|
||||
|
||||
if (bp[ndx + 1] == FULL_KEY) {
|
||||
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
|
||||
if (!bufp)
|
||||
return (-1);
|
||||
bp = (uint16 *)bufp->page;
|
||||
save_p = bufp;
|
||||
save_addr = save_p->addr;
|
||||
off = bp[1];
|
||||
len = 0;
|
||||
} else
|
||||
if (!FREESPACE(bp)) {
|
||||
/*
|
||||
* This is a hack. We can't distinguish between
|
||||
* FULL_KEY_DATA that contains complete data or
|
||||
* incomplete data, so we require that if the data
|
||||
* is complete, there is at least 1 byte of free
|
||||
* space left.
|
||||
*/
|
||||
off = bp[bp[0]];
|
||||
len = bp[1] - off;
|
||||
save_p = bufp;
|
||||
save_addr = bufp->addr;
|
||||
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
|
||||
if (!bufp)
|
||||
return (-1);
|
||||
bp = (uint16 *)bufp->page;
|
||||
} else {
|
||||
/* The data is all on one page. */
|
||||
tp = (char *)bp;
|
||||
off = bp[bp[0]];
|
||||
val->data = (uint8 *)tp + off;
|
||||
val->size = bp[1] - off;
|
||||
if (set_current) {
|
||||
if (bp[0] == 2) { /* No more buckets in
|
||||
* chain */
|
||||
hashp->cpage = NULL;
|
||||
hashp->cbucket++;
|
||||
hashp->cndx = 1;
|
||||
} else {
|
||||
hashp->cpage = __get_buf(hashp,
|
||||
bp[bp[0] - 1], bufp, 0);
|
||||
if (!hashp->cpage)
|
||||
return (-1);
|
||||
hashp->cndx = 1;
|
||||
if (!((uint16 *)
|
||||
hashp->cpage->page)[0]) {
|
||||
hashp->cbucket++;
|
||||
hashp->cpage = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* pin our saved buf so that we don't lose if
|
||||
* we run out of buffers */
|
||||
save_flags = save_p->flags;
|
||||
save_p->flags |= BUF_PIN;
|
||||
val->size = collect_data(hashp, bufp, (int)len, set_current);
|
||||
save_p->flags = save_flags;
|
||||
if (val->size == (size_t)-1)
|
||||
return (-1);
|
||||
if (save_p->addr != save_addr) {
|
||||
/* We are pretty short on buffers. */
|
||||
errno = EINVAL; /* OUT OF BUFFERS */
|
||||
return (-1);
|
||||
}
|
||||
memmove(hashp->tmp_buf, (save_p->page) + off, len);
|
||||
val->data = (uint8 *)hashp->tmp_buf;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Count how big the total datasize is by looping through the pages. Then
|
||||
* allocate a buffer and copy the data in the second loop. NOTE: Our caller
|
||||
* may already have a bp which it is holding onto. The caller is
|
||||
* responsible for copying that bp into our temp buffer. 'len' is how much
|
||||
* space to reserve for that buffer.
|
||||
*/
|
||||
static int
|
||||
collect_data(
|
||||
HTAB *hashp,
|
||||
BUFHEAD *bufp,
|
||||
int len, int set)
|
||||
{
|
||||
register uint16 *bp;
|
||||
BUFHEAD *save_bufp;
|
||||
int save_flags;
|
||||
int mylen, totlen;
|
||||
|
||||
/*
|
||||
* save the input buf head because we need to walk the list twice.
|
||||
* pin it to make sure it doesn't leave the buffer pool.
|
||||
* This has the effect of growing the buffer pool if necessary.
|
||||
*/
|
||||
save_bufp = bufp;
|
||||
save_flags = save_bufp->flags;
|
||||
save_bufp->flags |= BUF_PIN;
|
||||
|
||||
/* read the length of the buffer */
|
||||
for (totlen = len; bufp ; bufp = __get_buf(hashp, bp[bp[0]-1], bufp, 0)) {
|
||||
bp = (uint16 *)bufp->page;
|
||||
mylen = hashp->BSIZE - bp[1];
|
||||
|
||||
/* if mylen ever goes negative it means that the
|
||||
* page is screwed up.
|
||||
*/
|
||||
if (mylen < 0) {
|
||||
save_bufp->flags = save_flags;
|
||||
return (-1);
|
||||
}
|
||||
totlen += mylen;
|
||||
if (bp[2] == FULL_KEY_DATA) { /* End of Data */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bufp) {
|
||||
save_bufp->flags = save_flags;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* allocate a temp buf */
|
||||
if (hashp->tmp_buf)
|
||||
free(hashp->tmp_buf);
|
||||
if ((hashp->tmp_buf = (char *)malloc((size_t)totlen)) == NULL) {
|
||||
save_bufp->flags = save_flags;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* copy the buffers back into temp buf */
|
||||
for (bufp = save_bufp; bufp ;
|
||||
bufp = __get_buf(hashp, bp[bp[0]-1], bufp, 0)) {
|
||||
bp = (uint16 *)bufp->page;
|
||||
mylen = hashp->BSIZE - bp[1];
|
||||
memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], (size_t)mylen);
|
||||
len += mylen;
|
||||
if (bp[2] == FULL_KEY_DATA) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 'clear' the pin flags */
|
||||
save_bufp->flags = save_flags;
|
||||
|
||||
/* update the database cursor */
|
||||
if (set) {
|
||||
hashp->cndx = 1;
|
||||
if (bp[0] == 2) { /* No more buckets in chain */
|
||||
hashp->cpage = NULL;
|
||||
hashp->cbucket++;
|
||||
} else {
|
||||
hashp->cpage = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
|
||||
if (!hashp->cpage)
|
||||
return (-1);
|
||||
else if (!((uint16 *)hashp->cpage->page)[0]) {
|
||||
hashp->cbucket++;
|
||||
hashp->cpage = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (totlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the key and data for this big pair.
|
||||
*/
|
||||
extern int
|
||||
__big_keydata(
|
||||
HTAB *hashp,
|
||||
BUFHEAD *bufp,
|
||||
DBT *key, DBT *val,
|
||||
int set)
|
||||
{
|
||||
key->size = collect_key(hashp, bufp, 0, val, set);
|
||||
if (key->size == (size_t)-1)
|
||||
return (-1);
|
||||
key->data = (uint8 *)hashp->tmp_key;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count how big the total key size is by recursing through the pages. Then
|
||||
* collect the data, allocate a buffer and copy the key as you recurse up.
|
||||
*/
|
||||
static int
|
||||
collect_key(
|
||||
HTAB *hashp,
|
||||
BUFHEAD *bufp,
|
||||
int len,
|
||||
DBT *val,
|
||||
int set)
|
||||
{
|
||||
BUFHEAD *xbp;
|
||||
char *p;
|
||||
int mylen, totlen;
|
||||
uint16 *bp, save_addr;
|
||||
|
||||
p = bufp->page;
|
||||
bp = (uint16 *)p;
|
||||
mylen = hashp->BSIZE - bp[1];
|
||||
|
||||
save_addr = bufp->addr;
|
||||
totlen = len + mylen;
|
||||
if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */
|
||||
if (hashp->tmp_key != NULL)
|
||||
free(hashp->tmp_key);
|
||||
if ((hashp->tmp_key = (char *)malloc((size_t)totlen)) == NULL)
|
||||
return (-1);
|
||||
if (__big_return(hashp, bufp, 1, val, set))
|
||||
return (-1);
|
||||
} else {
|
||||
xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
|
||||
if (!xbp || ((totlen =
|
||||
collect_key(hashp, xbp, totlen, val, set)) < 1))
|
||||
return (-1);
|
||||
}
|
||||
if (bufp->addr != save_addr) {
|
||||
errno = EINVAL; /* MIS -- OUT OF BUFFERS */
|
||||
return (-1);
|
||||
}
|
||||
memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], (size_t)mylen);
|
||||
return (totlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* 0 => OK
|
||||
* -1 => error
|
||||
*/
|
||||
extern int
|
||||
__big_split(
|
||||
HTAB *hashp,
|
||||
BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
|
||||
BUFHEAD *np, /* Pointer to new bucket page */
|
||||
/* Pointer to first page containing the big key/data */
|
||||
BUFHEAD *big_keyp,
|
||||
uint32 addr, /* Address of big_keyp */
|
||||
uint32 obucket,/* Old Bucket */
|
||||
SPLIT_RETURN *ret)
|
||||
{
|
||||
register BUFHEAD *tmpp;
|
||||
register uint16 *tp;
|
||||
BUFHEAD *bp;
|
||||
DBT key, val;
|
||||
uint32 change;
|
||||
uint16 free_space, n, off;
|
||||
|
||||
bp = big_keyp;
|
||||
|
||||
/* Now figure out where the big key/data goes */
|
||||
if (__big_keydata(hashp, big_keyp, &key, &val, 0))
|
||||
return (-1);
|
||||
change = (__call_hash(hashp,(char*) key.data, key.size) != obucket);
|
||||
|
||||
if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) {
|
||||
if (!(ret->nextp =
|
||||
__get_buf(hashp, ret->next_addr, big_keyp, 0)))
|
||||
return (-1);;
|
||||
} else
|
||||
ret->nextp = NULL;
|
||||
|
||||
/* Now make one of np/op point to the big key/data pair */
|
||||
#ifdef DEBUG
|
||||
assert(np->ovfl == NULL);
|
||||
#endif
|
||||
if (change)
|
||||
tmpp = np;
|
||||
else
|
||||
tmpp = op;
|
||||
|
||||
tmpp->flags |= BUF_MOD;
|
||||
#ifdef DEBUG1
|
||||
(void)fprintf(stderr,
|
||||
"BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
|
||||
(tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
|
||||
#endif
|
||||
tmpp->ovfl = bp; /* one of op/np point to big_keyp */
|
||||
tp = (uint16 *)tmpp->page;
|
||||
|
||||
|
||||
#if 0 /* this get's tripped on database corrupted error */
|
||||
assert(FREESPACE(tp) >= OVFLSIZE);
|
||||
#endif
|
||||
if(FREESPACE(tp) < OVFLSIZE)
|
||||
return(DATABASE_CORRUPTED_ERROR);
|
||||
|
||||
n = tp[0];
|
||||
off = OFFSET(tp);
|
||||
free_space = FREESPACE(tp);
|
||||
tp[++n] = (uint16)addr;
|
||||
tp[++n] = OVFLPAGE;
|
||||
tp[0] = n;
|
||||
OFFSET(tp) = off;
|
||||
FREESPACE(tp) = free_space - OVFLSIZE;
|
||||
|
||||
/*
|
||||
* Finally, set the new and old return values. BIG_KEYP contains a
|
||||
* pointer to the last page of the big key_data pair. Make sure that
|
||||
* big_keyp has no following page (2 elements) or create an empty
|
||||
* following page.
|
||||
*/
|
||||
|
||||
ret->newp = np;
|
||||
ret->oldp = op;
|
||||
|
||||
tp = (uint16 *)big_keyp->page;
|
||||
big_keyp->flags |= BUF_MOD;
|
||||
if (tp[0] > 2) {
|
||||
/*
|
||||
* There may be either one or two offsets on this page. If
|
||||
* there is one, then the overflow page is linked on normally
|
||||
* and tp[4] is OVFLPAGE. If there are two, tp[4] contains
|
||||
* the second offset and needs to get stuffed in after the
|
||||
* next overflow page is added.
|
||||
*/
|
||||
n = tp[4];
|
||||
free_space = FREESPACE(tp);
|
||||
off = OFFSET(tp);
|
||||
tp[0] -= 2;
|
||||
FREESPACE(tp) = free_space + OVFLSIZE;
|
||||
OFFSET(tp) = off;
|
||||
tmpp = __add_ovflpage(hashp, big_keyp);
|
||||
if (!tmpp)
|
||||
return (-1);
|
||||
tp[4] = n;
|
||||
} else
|
||||
tmpp = big_keyp;
|
||||
|
||||
if (change)
|
||||
ret->newp = tmpp;
|
||||
else
|
||||
ret->oldp = tmpp;
|
||||
return (0);
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#ifndef macintosh
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include "mcom_db.h"
|
||||
#include "hash.h"
|
||||
#include "page.h"
|
||||
/* #include "extern.h" */
|
||||
|
||||
#if 0
|
||||
static uint32 hash1 __P((const void *, size_t));
|
||||
static uint32 hash2 __P((const void *, size_t));
|
||||
static uint32 hash3 __P((const void *, size_t));
|
||||
#endif
|
||||
static uint32 hash4 __P((const void *, size_t));
|
||||
|
||||
/* Global default hash function */
|
||||
uint32 (*__default_hash) __P((const void *, size_t)) = hash4;
|
||||
|
||||
/*
|
||||
* HASH FUNCTIONS
|
||||
*
|
||||
* Assume that we've already split the bucket to which this key hashes,
|
||||
* calculate that bucket, and check that in fact we did already split it.
|
||||
*
|
||||
* This came from ejb's hsearch.
|
||||
*/
|
||||
|
||||
#define PRIME1 37
|
||||
#define PRIME2 1048583
|
||||
|
||||
#if 0
|
||||
static uint32
|
||||
hash1(const void *keyarg, register size_t len)
|
||||
{
|
||||
register const uint8 *key;
|
||||
register uint32 h;
|
||||
|
||||
/* Convert string to integer */
|
||||
for (key = (const uint8 *)keyarg, h = 0; len--;)
|
||||
h = h * PRIME1 ^ (*key++ - ' ');
|
||||
h %= PRIME2;
|
||||
return (h);
|
||||
}
|
||||
|
||||
/*
|
||||
* Phong's linear congruential hash
|
||||
*/
|
||||
#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
|
||||
|
||||
static uint32
|
||||
hash2(const void *keyarg, size_t len)
|
||||
{
|
||||
register const uint8 *e, *key;
|
||||
register uint32 h;
|
||||
register uint8 c;
|
||||
|
||||
key = (const uint8 *)keyarg;
|
||||
e = key + len;
|
||||
for (h = 0; key != e;) {
|
||||
c = *key++;
|
||||
if (!c && key > e)
|
||||
break;
|
||||
dcharhash(h, c);
|
||||
}
|
||||
return (h);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is INCREDIBLY ugly, but fast. We break the string up into 8 byte
|
||||
* units. On the first time through the loop we get the "leftover bytes"
|
||||
* (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle
|
||||
* all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
|
||||
* this routine is heavily used enough, it's worth the ugly coding.
|
||||
*
|
||||
* OZ's original sdbm hash
|
||||
*/
|
||||
static uint32
|
||||
hash3(const void *keyarg, register size_t len)
|
||||
{
|
||||
register const uint8 *key;
|
||||
register size_t loop;
|
||||
register uint32 h;
|
||||
|
||||
#define HASHC h = *key++ + 65599 * h
|
||||
|
||||
h = 0;
|
||||
key = (const uint8 *)keyarg;
|
||||
if (len > 0) {
|
||||
loop = (len + 8 - 1) >> 3;
|
||||
|
||||
switch (len & (8 - 1)) {
|
||||
case 0:
|
||||
do {
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 6:
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 5:
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
HASHC;
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
HASHC;
|
||||
} while (--loop);
|
||||
}
|
||||
}
|
||||
return (h);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/* Hash function from Chris Torek. */
|
||||
static uint32
|
||||
hash4(const void *keyarg, register size_t len)
|
||||
{
|
||||
register const uint8 *key;
|
||||
register size_t loop;
|
||||
register uint32 h;
|
||||
|
||||
#define HASH4a h = (h << 5) - h + *key++;
|
||||
#define HASH4b h = (h << 5) + h + *key++;
|
||||
#define HASH4 HASH4b
|
||||
|
||||
h = 0;
|
||||
key = (const uint8 *)keyarg;
|
||||
if (len > 0) {
|
||||
loop = (len + 8 - 1) >> 3;
|
||||
|
||||
switch (len & (8 - 1)) {
|
||||
case 0:
|
||||
do {
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 6:
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 5:
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
HASH4;
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
HASH4;
|
||||
} while (--loop);
|
||||
}
|
||||
}
|
||||
return (h);
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifndef macintosh
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include "mcom_db.h"
|
||||
|
||||
uint32 __log2(uint32 num)
|
||||
{
|
||||
register uint32 i, limit;
|
||||
|
||||
limit = 1;
|
||||
for (i = 0; limit < num; limit = limit << 1, i++) {}
|
||||
return (i);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,410 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Margo Seltzer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/*
|
||||
* PACKAGE: hash
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Contains buffer management
|
||||
*
|
||||
* ROUTINES:
|
||||
* External
|
||||
* __buf_init
|
||||
* __get_buf
|
||||
* __buf_free
|
||||
* __reclaim_buf
|
||||
* Internal
|
||||
* newbuf
|
||||
*/
|
||||
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "mcom_db.h"
|
||||
#include "hash.h"
|
||||
#include "page.h"
|
||||
/* #include "extern.h" */
|
||||
|
||||
static BUFHEAD *newbuf __P((HTAB *, uint32, BUFHEAD *));
|
||||
|
||||
/* Unlink B from its place in the lru */
|
||||
#define BUF_REMOVE(B) { \
|
||||
(B)->prev->next = (B)->next; \
|
||||
(B)->next->prev = (B)->prev; \
|
||||
}
|
||||
|
||||
/* Insert B after P */
|
||||
#define BUF_INSERT(B, P) { \
|
||||
(B)->next = (P)->next; \
|
||||
(B)->prev = (P); \
|
||||
(P)->next = (B); \
|
||||
(B)->next->prev = (B); \
|
||||
}
|
||||
|
||||
#define MRU hashp->bufhead.next
|
||||
#define LRU hashp->bufhead.prev
|
||||
|
||||
#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead)
|
||||
#define LRU_INSERT(B) BUF_INSERT((B), LRU)
|
||||
|
||||
/*
|
||||
* We are looking for a buffer with address "addr". If prev_bp is NULL, then
|
||||
* address is a bucket index. If prev_bp is not NULL, then it points to the
|
||||
* page previous to an overflow page that we are trying to find.
|
||||
*
|
||||
* CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer
|
||||
* be valid. Therefore, you must always verify that its address matches the
|
||||
* address you are seeking.
|
||||
*/
|
||||
extern BUFHEAD *
|
||||
__get_buf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp, int newpage)
|
||||
/* If prev_bp set, indicates a new overflow page. */
|
||||
{
|
||||
register BUFHEAD *bp;
|
||||
register uint32 is_disk_mask;
|
||||
register int is_disk, segment_ndx = 0;
|
||||
SEGMENT segp = 0;
|
||||
|
||||
is_disk = 0;
|
||||
is_disk_mask = 0;
|
||||
if (prev_bp) {
|
||||
bp = prev_bp->ovfl;
|
||||
if (!bp || (bp->addr != addr))
|
||||
bp = NULL;
|
||||
if (!newpage)
|
||||
is_disk = BUF_DISK;
|
||||
} else {
|
||||
/* Grab buffer out of directory */
|
||||
segment_ndx = addr & (hashp->SGSIZE - 1);
|
||||
|
||||
/* valid segment ensured by __call_hash() */
|
||||
segp = hashp->dir[addr >> hashp->SSHIFT];
|
||||
#ifdef DEBUG
|
||||
assert(segp != NULL);
|
||||
#endif
|
||||
|
||||
bp = PTROF(segp[segment_ndx]);
|
||||
|
||||
is_disk_mask = ISDISK(segp[segment_ndx]);
|
||||
is_disk = is_disk_mask || !hashp->new_file;
|
||||
}
|
||||
|
||||
if (!bp) {
|
||||
bp = newbuf(hashp, addr, prev_bp);
|
||||
if (!bp)
|
||||
return(NULL);
|
||||
if(__get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
|
||||
{
|
||||
/* free bp and its page */
|
||||
if(prev_bp)
|
||||
{
|
||||
/* if prev_bp is set then the new page that
|
||||
* failed is hooked onto prev_bp as an overflow page.
|
||||
* if we don't remove the pointer to the bad page
|
||||
* we may try and access it later and we will die
|
||||
* horribly because it will have already been
|
||||
* free'd and overwritten with bogus data.
|
||||
*/
|
||||
prev_bp->ovfl = NULL;
|
||||
}
|
||||
BUF_REMOVE(bp);
|
||||
free(bp->page);
|
||||
free(bp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (!prev_bp)
|
||||
{
|
||||
#if 0
|
||||
/* 16 bit windows and mac can't handle the
|
||||
* oring of the is disk flag.
|
||||
*/
|
||||
segp[segment_ndx] =
|
||||
(BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
|
||||
#else
|
||||
/* set the is_disk thing inside the structure
|
||||
*/
|
||||
bp->is_disk = is_disk_mask;
|
||||
segp[segment_ndx] = bp;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
BUF_REMOVE(bp);
|
||||
MRU_INSERT(bp);
|
||||
}
|
||||
return (bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need a buffer for this page. Either allocate one, or evict a resident
|
||||
* one (if we have as many buffers as we're allowed) and put this one in.
|
||||
*
|
||||
* If newbuf finds an error (returning NULL), it also sets errno.
|
||||
*/
|
||||
static BUFHEAD *
|
||||
newbuf(HTAB *hashp, uint32 addr, BUFHEAD *prev_bp)
|
||||
{
|
||||
register BUFHEAD *bp; /* The buffer we're going to use */
|
||||
register BUFHEAD *xbp; /* Temp pointer */
|
||||
register BUFHEAD *next_xbp;
|
||||
SEGMENT segp;
|
||||
int segment_ndx;
|
||||
uint16 oaddr, *shortp;
|
||||
|
||||
oaddr = 0;
|
||||
bp = LRU;
|
||||
/*
|
||||
* If LRU buffer is pinned, the buffer pool is too small. We need to
|
||||
* allocate more buffers.
|
||||
*/
|
||||
if (hashp->nbufs || (bp->flags & BUF_PIN)) {
|
||||
/* Allocate a new one */
|
||||
if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* this memset is supposedly unnecessary but lets add
|
||||
* it anyways.
|
||||
*/
|
||||
memset(bp, 0xff, sizeof(BUFHEAD));
|
||||
|
||||
if ((bp->page = (char *)malloc((size_t)hashp->BSIZE)) == NULL) {
|
||||
free(bp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* this memset is supposedly unnecessary but lets add
|
||||
* it anyways.
|
||||
*/
|
||||
memset(bp->page, 0xff, (size_t)hashp->BSIZE);
|
||||
|
||||
if (hashp->nbufs)
|
||||
hashp->nbufs--;
|
||||
} else {
|
||||
/* Kick someone out */
|
||||
BUF_REMOVE(bp);
|
||||
/*
|
||||
* If this is an overflow page with addr 0, it's already been
|
||||
* flushed back in an overflow chain and initialized.
|
||||
*/
|
||||
if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
|
||||
/*
|
||||
* Set oaddr before __put_page so that you get it
|
||||
* before bytes are swapped.
|
||||
*/
|
||||
shortp = (uint16 *)bp->page;
|
||||
if (shortp[0])
|
||||
{
|
||||
if(shortp[0] > (hashp->BSIZE / sizeof(uint16)))
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
oaddr = shortp[shortp[0] - 1];
|
||||
}
|
||||
if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
|
||||
bp->addr, (int)IS_BUCKET(bp->flags), 0))
|
||||
return (NULL);
|
||||
/*
|
||||
* Update the pointer to this page (i.e. invalidate it).
|
||||
*
|
||||
* If this is a new file (i.e. we created it at open
|
||||
* time), make sure that we mark pages which have been
|
||||
* written to disk so we retrieve them from disk later,
|
||||
* rather than allocating new pages.
|
||||
*/
|
||||
if (IS_BUCKET(bp->flags)) {
|
||||
segment_ndx = bp->addr & (hashp->SGSIZE - 1);
|
||||
segp = hashp->dir[bp->addr >> hashp->SSHIFT];
|
||||
#ifdef DEBUG
|
||||
assert(segp != NULL);
|
||||
#endif
|
||||
|
||||
if (hashp->new_file &&
|
||||
((bp->flags & BUF_MOD) ||
|
||||
ISDISK(segp[segment_ndx])))
|
||||
segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
|
||||
else
|
||||
segp[segment_ndx] = NULL;
|
||||
}
|
||||
/*
|
||||
* Since overflow pages can only be access by means of
|
||||
* their bucket, free overflow pages associated with
|
||||
* this bucket.
|
||||
*/
|
||||
for (xbp = bp; xbp->ovfl;) {
|
||||
next_xbp = xbp->ovfl;
|
||||
xbp->ovfl = 0;
|
||||
xbp = next_xbp;
|
||||
|
||||
/* leave pinned pages alone, we are still using
|
||||
* them. */
|
||||
if (xbp->flags & BUF_PIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check that ovfl pointer is up date. */
|
||||
if (IS_BUCKET(xbp->flags) ||
|
||||
(oaddr != xbp->addr))
|
||||
break;
|
||||
|
||||
shortp = (uint16 *)xbp->page;
|
||||
if (shortp[0])
|
||||
{
|
||||
/* LJM is the number of reported
|
||||
* pages way too much?
|
||||
*/
|
||||
if(shortp[0] > hashp->BSIZE/sizeof(uint16))
|
||||
return NULL;
|
||||
/* set before __put_page */
|
||||
oaddr = shortp[shortp[0] - 1];
|
||||
}
|
||||
if ((xbp->flags & BUF_MOD) && __put_page(hashp,
|
||||
xbp->page, xbp->addr, 0, 0))
|
||||
return (NULL);
|
||||
xbp->addr = 0;
|
||||
xbp->flags = 0;
|
||||
BUF_REMOVE(xbp);
|
||||
LRU_INSERT(xbp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now assign this buffer */
|
||||
bp->addr = addr;
|
||||
#ifdef DEBUG1
|
||||
(void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
|
||||
bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
|
||||
#endif
|
||||
bp->ovfl = NULL;
|
||||
if (prev_bp) {
|
||||
/*
|
||||
* If prev_bp is set, this is an overflow page, hook it in to
|
||||
* the buffer overflow links.
|
||||
*/
|
||||
#ifdef DEBUG1
|
||||
(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
|
||||
prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
|
||||
(bp ? bp->addr : 0));
|
||||
#endif
|
||||
prev_bp->ovfl = bp;
|
||||
bp->flags = 0;
|
||||
} else
|
||||
bp->flags = BUF_BUCKET;
|
||||
MRU_INSERT(bp);
|
||||
return (bp);
|
||||
}
|
||||
|
||||
extern void __buf_init(HTAB *hashp, int32 nbytes)
|
||||
{
|
||||
BUFHEAD *bfp;
|
||||
int npages;
|
||||
|
||||
bfp = &(hashp->bufhead);
|
||||
npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
|
||||
npages = PR_MAX(npages, MIN_BUFFERS);
|
||||
|
||||
hashp->nbufs = npages;
|
||||
bfp->next = bfp;
|
||||
bfp->prev = bfp;
|
||||
/*
|
||||
* This space is calloc'd so these are already null.
|
||||
*
|
||||
* bfp->ovfl = NULL;
|
||||
* bfp->flags = 0;
|
||||
* bfp->page = NULL;
|
||||
* bfp->addr = 0;
|
||||
*/
|
||||
}
|
||||
|
||||
extern int
|
||||
__buf_free(HTAB *hashp, int do_free, int to_disk)
|
||||
{
|
||||
BUFHEAD *bp;
|
||||
int status = -1;
|
||||
|
||||
/* Need to make sure that buffer manager has been initialized */
|
||||
if (!LRU)
|
||||
return (0);
|
||||
for (bp = LRU; bp != &hashp->bufhead;) {
|
||||
/* Check that the buffer is valid */
|
||||
if (bp->addr || IS_BUCKET(bp->flags)) {
|
||||
if (to_disk && (bp->flags & BUF_MOD) &&
|
||||
(status = __put_page(hashp, bp->page,
|
||||
bp->addr, IS_BUCKET(bp->flags), 0))) {
|
||||
|
||||
if (do_free) {
|
||||
if (bp->page)
|
||||
free(bp->page);
|
||||
BUF_REMOVE(bp);
|
||||
free(bp);
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
/* Check if we are freeing stuff */
|
||||
if (do_free) {
|
||||
if (bp->page)
|
||||
free(bp->page);
|
||||
BUF_REMOVE(bp);
|
||||
free(bp);
|
||||
bp = LRU;
|
||||
} else
|
||||
bp = bp->prev;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
extern void
|
||||
__reclaim_buf(HTAB *hashp, BUFHEAD *bp)
|
||||
{
|
||||
bp->ovfl = 0;
|
||||
bp->addr = 0;
|
||||
bp->flags = 0;
|
||||
BUF_REMOVE(bp);
|
||||
LRU_INSERT(bp);
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#if defined(__sun) && !defined(__SVR4)
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#ifdef HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#else
|
||||
#include "cdefs.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* sizeof(word) MUST BE A POWER OF TWO
|
||||
* SO THAT wmask BELOW IS ALL ONES
|
||||
*/
|
||||
typedef int word; /* "word" used for optimal copy speed */
|
||||
|
||||
#define wsize sizeof(word)
|
||||
#define wmask (wsize - 1)
|
||||
|
||||
/*
|
||||
* Copy a block of memory, handling overlap.
|
||||
* This is the routine that actually implements
|
||||
* (the portable versions of) bcopy, memcpy, and memmove.
|
||||
*/
|
||||
#ifdef MEMCOPY
|
||||
void *
|
||||
memcpy(dst0, src0, length)
|
||||
#else
|
||||
#ifdef MEMMOVE
|
||||
void *
|
||||
memmove(dst0, src0, length)
|
||||
#else
|
||||
void
|
||||
bcopy(src0, dst0, length)
|
||||
#endif
|
||||
#endif
|
||||
void *dst0;
|
||||
const void *src0;
|
||||
register size_t length;
|
||||
{
|
||||
register char *dst = dst0;
|
||||
register const char *src = src0;
|
||||
register size_t t;
|
||||
|
||||
if (length == 0 || dst == src) /* nothing to do */
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Macros: loop-t-times; and loop-t-times, t>0
|
||||
*/
|
||||
#define TLOOP(s) if (t) TLOOP1(s)
|
||||
#define TLOOP1(s) do { s; } while (--t)
|
||||
|
||||
if ((unsigned long)dst < (unsigned long)src) {
|
||||
/*
|
||||
* Copy forward.
|
||||
*/
|
||||
t = (int)src; /* only need low bits */
|
||||
if ((t | (int)dst) & wmask) {
|
||||
/*
|
||||
* Try to align operands. This cannot be done
|
||||
* unless the low bits match.
|
||||
*/
|
||||
if ((t ^ (int)dst) & wmask || length < wsize)
|
||||
t = length;
|
||||
else
|
||||
t = wsize - (t & wmask);
|
||||
length -= t;
|
||||
TLOOP1(*dst++ = *src++);
|
||||
}
|
||||
/*
|
||||
* Copy whole words, then mop up any trailing bytes.
|
||||
*/
|
||||
t = length / wsize;
|
||||
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
|
||||
t = length & wmask;
|
||||
TLOOP(*dst++ = *src++);
|
||||
} else {
|
||||
/*
|
||||
* Copy backwards. Otherwise essentially the same.
|
||||
* Alignment works as before, except that it takes
|
||||
* (t&wmask) bytes to align, not wsize-(t&wmask).
|
||||
*/
|
||||
src += length;
|
||||
dst += length;
|
||||
t = (int)src;
|
||||
if ((t | (int)dst) & wmask) {
|
||||
if ((t ^ (int)dst) & wmask || length <= wsize)
|
||||
t = length;
|
||||
else
|
||||
t &= wmask;
|
||||
length -= t;
|
||||
TLOOP1(*--dst = *--src);
|
||||
}
|
||||
t = length / wsize;
|
||||
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
|
||||
t = length & wmask;
|
||||
TLOOP(*--dst = *--src);
|
||||
}
|
||||
done:
|
||||
#if defined(MEMCOPY) || defined(MEMMOVE)
|
||||
return (dst0);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
#endif /* no __sgi */
|
||||
|
||||
/* Some compilers don't like an empty source file. */
|
||||
static int dummy = 0;
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#ifdef macintosh
|
||||
#include <unix.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "mcom_db.h"
|
||||
|
||||
#ifndef _WINDOWS
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <process.h>
|
||||
#include "winfile.h"
|
||||
#endif
|
||||
|
||||
static int _gettemp(char *path, register int *doopen, int extraFlags);
|
||||
|
||||
int
|
||||
mkstemp(char *path)
|
||||
{
|
||||
#ifdef XP_OS2
|
||||
FILE *temp = tmpfile();
|
||||
|
||||
return (temp ? fileno(temp) : -1);
|
||||
#else
|
||||
int fd;
|
||||
|
||||
return (_gettemp(path, &fd, 0) ? fd : -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
mkstempflags(char *path, int extraFlags)
|
||||
{
|
||||
int fd;
|
||||
|
||||
return (_gettemp(path, &fd, extraFlags) ? fd : -1);
|
||||
}
|
||||
|
||||
#ifdef WINCE /* otherwise, use the one in libc */
|
||||
char *
|
||||
mktemp(char *path)
|
||||
{
|
||||
return(_gettemp(path, (int *)NULL, 0) ? path : (char *)NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* NB: This routine modifies its input string, and does not always restore it.
|
||||
** returns 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
_gettemp(char *path, register int *doopen, int extraFlags)
|
||||
{
|
||||
#if !defined(_WINDOWS) || defined(_WIN32)
|
||||
extern int errno;
|
||||
#endif
|
||||
register char *start, *trv;
|
||||
struct stat sbuf;
|
||||
unsigned int pid;
|
||||
|
||||
pid = getpid();
|
||||
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
|
||||
while (*--trv == 'X') {
|
||||
*trv = (pid % 10) + '0';
|
||||
pid /= 10;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the target directory; if you have six X's and it
|
||||
* doesn't exist this runs for a *very* long time.
|
||||
*/
|
||||
for (start = trv + 1;; --trv) {
|
||||
char saved;
|
||||
if (trv <= path)
|
||||
break;
|
||||
saved = *trv;
|
||||
if (saved == '/' || saved == '\\') {
|
||||
int rv;
|
||||
*trv = '\0';
|
||||
rv = stat(path, &sbuf);
|
||||
*trv = saved;
|
||||
if (rv)
|
||||
return(0);
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (doopen) {
|
||||
if ((*doopen =
|
||||
open(path, O_CREAT|O_EXCL|O_RDWR|extraFlags, 0600)) >= 0)
|
||||
return(1);
|
||||
if (errno != EEXIST)
|
||||
return(0);
|
||||
}
|
||||
else if (stat(path, &sbuf))
|
||||
return(errno == ENOENT ? 1 : 0);
|
||||
|
||||
/* tricky little algorithm for backward compatibility */
|
||||
for (trv = start;;) {
|
||||
if (!*trv)
|
||||
return(0);
|
||||
if (*trv == 'z')
|
||||
*trv++ = 'a';
|
||||
else {
|
||||
if (isdigit(*trv))
|
||||
*trv = 'a';
|
||||
else
|
||||
++*trv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#ifndef HAVE_SNPRINTF
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#else
|
||||
#include "cdefs.h"
|
||||
#endif
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
#include <ncompat.h>
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
#ifdef __STDC__
|
||||
snprintf(char *str, size_t n, const char *fmt, ...)
|
||||
#else
|
||||
snprintf(str, n, fmt, va_alist)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#ifdef VSPRINTF_CHARSTAR
|
||||
char *rp;
|
||||
#else
|
||||
int rval;
|
||||
#endif
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
#ifdef VSPRINTF_CHARSTAR
|
||||
rp = vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (strlen(rp));
|
||||
#else
|
||||
rval = vsprintf(str, fmt, ap);
|
||||
va_end(ap);
|
||||
return (rval);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
vsnprintf(str, n, fmt, ap)
|
||||
char *str;
|
||||
size_t n;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
#ifdef VSPRINTF_CHARSTAR
|
||||
return (strlen(vsprintf(str, fmt, ap)));
|
||||
#else
|
||||
return (vsprintf(str, fmt, ap));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HAVE_SNPRINTF */
|
||||
|
||||
/* Some compilers don't like an empty source file. */
|
||||
static int dummy = 0;
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. ***REMOVED*** - see
|
||||
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _DLL
|
||||
#define sys_nerr (*_sys_nerr_dll)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
#ifndef _AFXDLL
|
||||
char *
|
||||
strerror(num)
|
||||
int num;
|
||||
{
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#define UPREFIX "Unknown error: "
|
||||
static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
|
||||
register unsigned int errnum;
|
||||
register char *p, *t;
|
||||
char tmp[40];
|
||||
|
||||
errnum = num; /* convert to unsigned */
|
||||
if (errnum < sys_nerr)
|
||||
return(sys_errlist[errnum]);
|
||||
|
||||
/* Do this by hand, so we don't include stdio(3). */
|
||||
t = tmp;
|
||||
do {
|
||||
*t++ = "0123456789"[errnum % 10];
|
||||
} while (errnum /= 10);
|
||||
for (p = ebuf + sizeof(UPREFIX) - 1;;) {
|
||||
*p++ = *--t;
|
||||
if (t <= tmp)
|
||||
break;
|
||||
}
|
||||
return(ebuf);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* !HAVE_STRERROR */
|
||||
@@ -1,62 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dbm
|
||||
|
||||
PACKAGE_FILE = dbmtest.pkg
|
||||
|
||||
PROGRAM = lots$(BIN_SUFFIX)
|
||||
|
||||
CSRCS = lots.c
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
EXTRA_DSO_LIBS = dbm$(MOZ_BITS)
|
||||
else
|
||||
EXTRA_DSO_LIBS = mozdbm_s
|
||||
endif
|
||||
|
||||
LIBS = $(EXTRA_DSO_LIBS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[gecko-tests]
|
||||
dist/bin/lots@BINS@
|
||||
@@ -1,638 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* use sequental numbers printed to strings
|
||||
* to store lots and lots of entries in the
|
||||
* database.
|
||||
*
|
||||
* Start with 100 entries, put them and then
|
||||
* read them out. Then delete the first
|
||||
* half and verify that all of the first half
|
||||
* is gone and then verify that the second
|
||||
* half is still there.
|
||||
* Then add the first half back and verify
|
||||
* again. Then delete the middle third
|
||||
* and verify again.
|
||||
* Then increase the size by 1000 and do
|
||||
* the whole add delete thing again.
|
||||
*
|
||||
* The data for each object is the number string translated
|
||||
* to hex and replicated a random number of times. The
|
||||
* number of times that the data is replicated is the first
|
||||
* int32 in the data.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "mcom_db.h"
|
||||
|
||||
DB *database=0;
|
||||
int MsgPriority=5;
|
||||
|
||||
#if defined(_WINDOWS) && !defined(WIN32)
|
||||
#define int32 long
|
||||
#define uint32 unsigned long
|
||||
#else
|
||||
#define int32 int
|
||||
#define uint32 unsigned int
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
USE_LARGE_KEY,
|
||||
USE_SMALL_KEY
|
||||
} key_type_enum;
|
||||
|
||||
#define TraceMe(priority, msg) \
|
||||
do { \
|
||||
if(priority <= MsgPriority) \
|
||||
{ \
|
||||
ReportStatus msg; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int
|
||||
ReportStatus(char *string, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
va_start(args, string);
|
||||
#else
|
||||
va_start(args);
|
||||
#endif
|
||||
vfprintf(stderr, string, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
ReportError(char *string, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
va_start(args, string);
|
||||
#else
|
||||
va_start(args);
|
||||
#endif
|
||||
fprintf (stderr, "\n ");
|
||||
vfprintf(stderr, string, args);
|
||||
fprintf (stderr, "\n");
|
||||
va_end(args);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
DBT * MakeLargeKey(int32 num)
|
||||
{
|
||||
int32 low_bits;
|
||||
static DBT rv;
|
||||
static char *string_rv=0;
|
||||
int rep_char;
|
||||
size_t size;
|
||||
|
||||
if(string_rv)
|
||||
free(string_rv);
|
||||
|
||||
/* generate a really large text key derived from
|
||||
* an int32
|
||||
*/
|
||||
low_bits = (num % 10000) + 1;
|
||||
|
||||
/* get the repeat char from the low 26 */
|
||||
rep_char = (char) ((low_bits % 26) + 'a');
|
||||
|
||||
/* malloc a string low_bits wide */
|
||||
size = low_bits*sizeof(char);
|
||||
string_rv = (char *)malloc(size);
|
||||
|
||||
memset(string_rv, rep_char, size);
|
||||
|
||||
rv.data = string_rv;
|
||||
rv.size = size;
|
||||
|
||||
return(&rv);
|
||||
}
|
||||
|
||||
DBT * MakeSmallKey(int32 num)
|
||||
{
|
||||
static DBT rv;
|
||||
static char data_string[64];
|
||||
|
||||
rv.data = data_string;
|
||||
|
||||
sprintf(data_string, "%ld", (long)num);
|
||||
rv.size = strlen(data_string);
|
||||
|
||||
return(&rv);
|
||||
|
||||
}
|
||||
|
||||
DBT * GenKey(int32 num, key_type_enum key_type)
|
||||
{
|
||||
DBT *key;
|
||||
|
||||
switch(key_type)
|
||||
{
|
||||
case USE_LARGE_KEY:
|
||||
key = MakeLargeKey(num);
|
||||
break;
|
||||
case USE_SMALL_KEY:
|
||||
key = MakeSmallKey(num);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
|
||||
return(key);
|
||||
}
|
||||
|
||||
int
|
||||
SeqDatabase()
|
||||
{
|
||||
int status;
|
||||
DBT key, data;
|
||||
|
||||
ReportStatus("SEQuencing through database...");
|
||||
|
||||
/* seq through the whole database */
|
||||
if(!(status = (*database->seq)(database, &key, &data, R_FIRST)))
|
||||
{
|
||||
while(!(status = (database->seq) (database, &key, &data, R_NEXT)))
|
||||
; /* null body */
|
||||
}
|
||||
|
||||
if(status < 0)
|
||||
ReportError("Error seq'ing database");
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
int
|
||||
VerifyData(DBT *data, int32 num, key_type_enum key_type)
|
||||
{
|
||||
int32 count, compare_num;
|
||||
size_t size;
|
||||
int32 *int32_array;
|
||||
|
||||
/* The first int32 is count
|
||||
* The other n entries should
|
||||
* all equal num
|
||||
*/
|
||||
if(data->size < sizeof(int32))
|
||||
{
|
||||
ReportError("Data size corrupted");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&count, data->data, sizeof(int32));
|
||||
|
||||
size = sizeof(int32)*(count+1);
|
||||
|
||||
if(size != data->size)
|
||||
{
|
||||
ReportError("Data size corrupted");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_array = (int32*)data->data;
|
||||
|
||||
for(;count > 0; count--)
|
||||
{
|
||||
memcpy(&compare_num, &int32_array[count], sizeof(int32));
|
||||
|
||||
if(compare_num != num)
|
||||
{
|
||||
ReportError("Data corrupted");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* verify that a range of number strings exist
|
||||
* or don't exist. And that the data is valid
|
||||
*/
|
||||
#define SHOULD_EXIST 1
|
||||
#define SHOULD_NOT_EXIST 0
|
||||
int
|
||||
VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type)
|
||||
{
|
||||
DBT *key, data;
|
||||
int32 num;
|
||||
int status;
|
||||
|
||||
TraceMe(1, ("Verifying: %ld to %ld, using %s keys",
|
||||
low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
|
||||
|
||||
for(num = low; num <= high; num++)
|
||||
{
|
||||
|
||||
key = GenKey(num, key_type);
|
||||
|
||||
status = (*database->get)(database, key, &data, 0);
|
||||
|
||||
if(status == 0)
|
||||
{
|
||||
/* got the item */
|
||||
if(!should_exist)
|
||||
{
|
||||
ReportError("Item exists but shouldn't: %ld", num);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* else verify the data */
|
||||
VerifyData(&data, num, key_type);
|
||||
}
|
||||
}
|
||||
else if(status > 0)
|
||||
{
|
||||
/* item not found */
|
||||
if(should_exist)
|
||||
{
|
||||
ReportError("Item not found but should be: %ld", num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* database error */
|
||||
ReportError("Database error");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TraceMe(1, ("Correctly verified: %ld to %ld", low, high));
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
DBT *
|
||||
GenData(int32 num)
|
||||
{
|
||||
int32 n;
|
||||
static DBT *data=0;
|
||||
int32 *int32_array;
|
||||
size_t size;
|
||||
|
||||
if(!data)
|
||||
{
|
||||
data = (DBT*)malloc(sizeof(DBT));
|
||||
data->size = 0;
|
||||
data->data = 0;
|
||||
}
|
||||
else if(data->data)
|
||||
{
|
||||
free(data->data);
|
||||
}
|
||||
|
||||
n = rand();
|
||||
|
||||
n = n % 512; /* bound to a 2K size */
|
||||
|
||||
|
||||
size = sizeof(int32)*(n+1);
|
||||
int32_array = (int32 *) malloc(size);
|
||||
|
||||
memcpy(&int32_array[0], &n, sizeof(int32));
|
||||
|
||||
for(; n > 0; n--)
|
||||
{
|
||||
memcpy(&int32_array[n], &num, sizeof(int32));
|
||||
}
|
||||
|
||||
data->data = (void*)int32_array;
|
||||
data->size = size;
|
||||
|
||||
return(data);
|
||||
}
|
||||
|
||||
#define ADD_RANGE 1
|
||||
#define DELETE_RANGE 2
|
||||
|
||||
int
|
||||
AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type)
|
||||
{
|
||||
DBT *key, *data;
|
||||
#if 0 /* only do this if your really analy checking the puts */
|
||||
DBT tmp_data;
|
||||
#endif
|
||||
int32 num;
|
||||
int status;
|
||||
|
||||
if(action != ADD_RANGE && action != DELETE_RANGE)
|
||||
assert(0);
|
||||
|
||||
if(action == ADD_RANGE)
|
||||
{
|
||||
TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high,
|
||||
key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high,
|
||||
key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
|
||||
}
|
||||
|
||||
for(num = low; num <= high; num++)
|
||||
{
|
||||
|
||||
key = GenKey(num, key_type);
|
||||
|
||||
if(action == ADD_RANGE)
|
||||
{
|
||||
data = GenData(num);
|
||||
status = (*database->put)(database, key, data, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = (*database->del)(database, key, 0);
|
||||
}
|
||||
|
||||
if(status < 0)
|
||||
{
|
||||
ReportError("Database error %s item: %ld",
|
||||
action == ADD_RANGE ? "ADDING" : "DELETING",
|
||||
num);
|
||||
}
|
||||
else if(status > 0)
|
||||
{
|
||||
ReportError("Could not %s item: %ld",
|
||||
action == ADD_RANGE ? "ADD" : "DELETE",
|
||||
num);
|
||||
}
|
||||
else if(action == ADD_RANGE)
|
||||
{
|
||||
#define SYNC_EVERY_TIME
|
||||
#ifdef SYNC_EVERY_TIME
|
||||
status = (*database->sync)(database, 0);
|
||||
if(status != 0)
|
||||
ReportError("Database error syncing after add");
|
||||
#endif
|
||||
|
||||
#if 0 /* only do this if your really analy checking the puts */
|
||||
|
||||
/* make sure we can still get it
|
||||
*/
|
||||
status = (*database->get)(database, key, &tmp_data, 0);
|
||||
|
||||
if(status != 0)
|
||||
{
|
||||
ReportError("Database error checking item just added: %d",
|
||||
num);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* now verify that none of the ones we already
|
||||
* put in have disappeared
|
||||
*/
|
||||
VerifyRange(low, num, SHOULD_EXIST, key_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(action == ADD_RANGE)
|
||||
{
|
||||
TraceMe(1, ("Successfully added: %ld to %ld", low, high));
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceMe(1, ("Successfully deleted: %ld to %ld", low, high));
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
TestRange(int32 low, int32 range, key_type_enum key_type)
|
||||
{
|
||||
int status; int32 low_of_range1, high_of_range1; int32 low_of_range2, high_of_range2;
|
||||
int32 low_of_range3, high_of_range3;
|
||||
|
||||
status = AddOrDelRange(low, low+range, ADD_RANGE, key_type);
|
||||
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 1"));
|
||||
|
||||
SeqDatabase();
|
||||
|
||||
low_of_range1 = low;
|
||||
high_of_range1 = low+(range/2);
|
||||
low_of_range2 = high_of_range1+1;
|
||||
high_of_range2 = low+range;
|
||||
status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type);
|
||||
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type);
|
||||
status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 2"));
|
||||
|
||||
SeqDatabase();
|
||||
|
||||
status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type);
|
||||
/* the whole thing should exist now */
|
||||
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 3"));
|
||||
|
||||
SeqDatabase();
|
||||
|
||||
status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
|
||||
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
|
||||
status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 4"));
|
||||
|
||||
SeqDatabase();
|
||||
|
||||
status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
|
||||
/* the whole thing should exist now */
|
||||
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 5"));
|
||||
|
||||
SeqDatabase();
|
||||
|
||||
low_of_range1 = low;
|
||||
high_of_range1 = low+(range/3);
|
||||
low_of_range2 = high_of_range1+1;
|
||||
high_of_range2 = high_of_range1+(range/3);
|
||||
low_of_range3 = high_of_range2+1;
|
||||
high_of_range3 = low+range;
|
||||
/* delete range 2 */
|
||||
status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
|
||||
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
|
||||
status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type);
|
||||
status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 6"));
|
||||
|
||||
SeqDatabase();
|
||||
|
||||
status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
|
||||
/* the whole thing should exist now */
|
||||
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
|
||||
|
||||
TraceMe(1, ("Finished with sub test 7"));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define START_RANGE 109876
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int32 i, j=0;
|
||||
int quick_exit = 0;
|
||||
int large_keys = 0;
|
||||
HASHINFO hash_info = {
|
||||
16*1024,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
while(argc > 1)
|
||||
{
|
||||
if(!strcmp(argv[argc-1], "-quick"))
|
||||
quick_exit = 1;
|
||||
else if(!strcmp(argv[argc-1], "-large"))
|
||||
{
|
||||
large_keys = 1;
|
||||
}
|
||||
argc--;
|
||||
}
|
||||
}
|
||||
|
||||
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info);
|
||||
|
||||
if(!database)
|
||||
{
|
||||
ReportError("Could not open database");
|
||||
#ifdef unix
|
||||
perror("");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(quick_exit)
|
||||
{
|
||||
if(large_keys)
|
||||
TestRange(START_RANGE, 200, USE_LARGE_KEY);
|
||||
else
|
||||
TestRange(START_RANGE, 200, USE_SMALL_KEY);
|
||||
|
||||
(*database->sync)(database, 0);
|
||||
(*database->close)(database);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for(i=100; i < 10000000; i+=200)
|
||||
{
|
||||
if(1 || j)
|
||||
{
|
||||
TestRange(START_RANGE, i, USE_LARGE_KEY);
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
TestRange(START_RANGE, i, USE_SMALL_KEY);
|
||||
j = 1;
|
||||
}
|
||||
|
||||
if(1 == rand() % 3)
|
||||
{
|
||||
(*database->sync)(database, 0);
|
||||
}
|
||||
|
||||
if(1 == rand() % 3)
|
||||
{
|
||||
/* close and reopen */
|
||||
(*database->close)(database);
|
||||
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
|
||||
if(!database)
|
||||
{
|
||||
ReportError("Could not reopen database");
|
||||
#ifdef unix
|
||||
perror("");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reopen database without closeing the other */
|
||||
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
|
||||
if(!database)
|
||||
{
|
||||
ReportError("Could not reopen database "
|
||||
"after not closing the other");
|
||||
#ifdef unix
|
||||
perror("");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
ifdef NSS_DISABLE_DBM
|
||||
DIRS = dummy
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
coreconf_hack:
|
||||
cd ../coreconf; gmake
|
||||
gmake import
|
||||
|
||||
RelEng_bld: coreconf_hack
|
||||
gmake
|
||||
@@ -1,71 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# These macros are defined by mozilla's configure script.
|
||||
# We define them manually here.
|
||||
#
|
||||
|
||||
DEFINES += -DSTDC_HEADERS -DHAVE_STRERROR
|
||||
|
||||
#
|
||||
# Most platforms have snprintf, so it's simpler to list the exceptions.
|
||||
#
|
||||
HAVE_SNPRINTF = 1
|
||||
#
|
||||
# OSF1 V4.0D doesn't have snprintf but V5.0A does.
|
||||
#
|
||||
ifeq ($(OS_TARGET)$(OS_RELEASE),OSF1V4.0D)
|
||||
HAVE_SNPRINTF =
|
||||
endif
|
||||
ifdef HAVE_SNPRINTF
|
||||
DEFINES += -DHAVE_SNPRINTF
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out IRIX Linux,$(OS_TARGET)))
|
||||
DEFINES += -DHAVE_SYS_CDEFS_H
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out DGUX NCR ReliantUNIX SCO_SV SCOOS UNIXWARE,$(OS_TARGET)))
|
||||
DEFINES += -DHAVE_SYS_BYTEORDER_H
|
||||
endif
|
||||
|
||||
#
|
||||
# None of the platforms that we are interested in need to
|
||||
# define HAVE_MEMORY_H.
|
||||
#
|
||||
@@ -1,80 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
CORE_DEPTH = ../..
|
||||
|
||||
VPATH = $(CORE_DEPTH)/../dbm/include
|
||||
|
||||
MODULE = dbm
|
||||
|
||||
EXPORTS = cdefs.h \
|
||||
mcom_db.h \
|
||||
ncompat.h \
|
||||
winfile.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = hsearch.h \
|
||||
page.h \
|
||||
extern.h \
|
||||
queue.h \
|
||||
hash.h \
|
||||
mpool.h \
|
||||
search.h \
|
||||
$(NULL)
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
CORE_DEPTH = ..
|
||||
|
||||
MODULE = dbm
|
||||
|
||||
IMPORTS = nspr20/v4.4.1
|
||||
|
||||
RELEASE = dbm
|
||||
|
||||
DIRS = include \
|
||||
src \
|
||||
$(NULL)
|
||||
@@ -1,80 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/dbm/config/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include config.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEFINES += -DMEMMOVE -D__DBINTERFACE_PRIVATE $(SECURITY_FLAG)
|
||||
|
||||
INCLUDES += -I$(CORE_DEPTH)/../dbm/include
|
||||
|
||||
#
|
||||
# Currently, override TARGETS variable so that only static libraries
|
||||
# are specifed as dependencies within rules.mk.
|
||||
#
|
||||
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PURE_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
ifdef SHARED_LIBRARY
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
DLLBASE=/BASE:0x30000000
|
||||
RES=$(OBJDIR)/dbm.res
|
||||
RESNAME=../include/dbm.rc
|
||||
endif
|
||||
ifeq ($(DLL_SUFFIX),dll)
|
||||
DEFINES += -D_DLL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),AIX)
|
||||
OS_LIBS += -lc_r
|
||||
endif
|
||||
@@ -1,348 +0,0 @@
|
||||
#ifdef OS2
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*#ifndef __EMX__
|
||||
#include <libx.h>
|
||||
#endif */
|
||||
|
||||
#define INCL_DOSFILEMGR
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
#if OS2 >= 2
|
||||
# define FFBUF FILEFINDBUF3
|
||||
# define Word ULONG
|
||||
/*
|
||||
* LS20 recommends a request count of 100, but according to the
|
||||
* APAR text it does not lead to missing files, just to funny
|
||||
* numbers of returned entries.
|
||||
*
|
||||
* LS30 HPFS386 requires a count greater than 2, or some files
|
||||
* are missing (those starting with a character less that '.').
|
||||
*
|
||||
* Novell loses entries which overflow the buffer. In previous
|
||||
* versions of dirent2, this could have lead to missing files
|
||||
* when the average length of 100 directory entries was 40 bytes
|
||||
* or more (quite unlikely for files on a Novell server).
|
||||
*
|
||||
* Conclusion: Make sure that the entries all fit into the buffer
|
||||
* and that the buffer is large enough for more than 2 entries
|
||||
* (each entry is at most 300 bytes long). And ignore the LS20
|
||||
* effect.
|
||||
*/
|
||||
# define Count 25
|
||||
# define BufSz (25 * (sizeof(FILEFINDBUF3)+1))
|
||||
#else
|
||||
# define FFBUF FILEFINDBUF
|
||||
# define Word USHORT
|
||||
# define BufSz 1024
|
||||
# define Count 3
|
||||
#endif
|
||||
|
||||
#if defined(__IBMC__) || defined(__IBMCPP__)
|
||||
#define error(rc) _doserrno = rc, errno = EOS2ERR
|
||||
#elif defined(MICROSOFT)
|
||||
#define error(rc) _doserrno = rc, errno = 255
|
||||
#else
|
||||
#define error(rc) errno = 255
|
||||
#endif
|
||||
|
||||
struct _dirdescr {
|
||||
HDIR handle; /* DosFindFirst handle */
|
||||
char fstype; /* filesystem type */
|
||||
Word count; /* valid entries in <ffbuf> */
|
||||
long number; /* absolute number of next entry */
|
||||
int index; /* relative number of next entry */
|
||||
FFBUF * next; /* pointer to next entry */
|
||||
char name[MAXPATHLEN+3]; /* directory name */
|
||||
unsigned attrmask; /* attribute mask for seekdir */
|
||||
struct dirent entry; /* buffer for directory entry */
|
||||
BYTE ffbuf[BufSz];
|
||||
};
|
||||
|
||||
/*
|
||||
* Return first char of filesystem type, or 0 if unknown.
|
||||
*/
|
||||
static char
|
||||
getFSType(const char *path)
|
||||
{
|
||||
static char cache[1+26];
|
||||
char drive[3], info[512];
|
||||
Word unit, infolen;
|
||||
char r;
|
||||
|
||||
if (isalpha(path[0]) && path[1] == ':') {
|
||||
unit = toupper(path[0]) - '@';
|
||||
path += 2;
|
||||
} else {
|
||||
ULONG driveMap;
|
||||
#if OS2 >= 2
|
||||
if (DosQueryCurrentDisk(&unit, &driveMap))
|
||||
#else
|
||||
if (DosQCurDisk(&unit, &driveMap))
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((path[0] == '\\' || path[0] == '/')
|
||||
&& (path[1] == '\\' || path[1] == '/'))
|
||||
return 0;
|
||||
|
||||
if (cache [unit])
|
||||
return cache [unit];
|
||||
|
||||
drive[0] = '@' + unit;
|
||||
drive[1] = ':';
|
||||
drive[2] = '\0';
|
||||
infolen = sizeof info;
|
||||
#if OS2 >= 2
|
||||
if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen))
|
||||
return 0;
|
||||
if (infolen >= sizeof(FSQBUFFER2)) {
|
||||
FSQBUFFER2 *p = (FSQBUFFER2 *)info;
|
||||
r = p->szFSDName[p->cbName];
|
||||
} else
|
||||
#else
|
||||
if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen, 0))
|
||||
return 0;
|
||||
if (infolen >= 9) {
|
||||
char *p = info + sizeof(USHORT);
|
||||
p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT);
|
||||
r = *p;
|
||||
} else
|
||||
#endif
|
||||
r = 0;
|
||||
return cache [unit] = r;
|
||||
}
|
||||
|
||||
char *
|
||||
abs_path(const char *name, char *buffer, int len)
|
||||
{
|
||||
char buf[4];
|
||||
if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
|
||||
buf[0] = name[0];
|
||||
buf[1] = name[1];
|
||||
buf[2] = '.';
|
||||
buf[3] = '\0';
|
||||
name = buf;
|
||||
}
|
||||
#if OS2 >= 2
|
||||
if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len))
|
||||
#else
|
||||
if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L))
|
||||
#endif
|
||||
return NULL;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
DIR *
|
||||
openxdir(const char *path, unsigned att_mask)
|
||||
{
|
||||
DIR *dir;
|
||||
char name[MAXPATHLEN+3];
|
||||
Word rc;
|
||||
|
||||
dir = malloc(sizeof(DIR));
|
||||
if (dir == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(name, path, MAXPATHLEN);
|
||||
name[MAXPATHLEN] = '\0';
|
||||
switch (name[strlen(name)-1]) {
|
||||
default:
|
||||
strcat(name, "\\");
|
||||
case '\\':
|
||||
case '/':
|
||||
case ':':
|
||||
;
|
||||
}
|
||||
strcat(name, ".");
|
||||
if (!abs_path(name, dir->name, MAXPATHLEN+1))
|
||||
strcpy(dir->name, name);
|
||||
if (dir->name[strlen(dir->name)-1] == '\\')
|
||||
strcat(dir->name, "*");
|
||||
else
|
||||
strcat(dir->name, "\\*");
|
||||
|
||||
dir->fstype = getFSType(dir->name);
|
||||
dir->attrmask = att_mask | A_DIR;
|
||||
|
||||
dir->handle = HDIR_CREATE;
|
||||
dir->count = 100;
|
||||
#if OS2 >= 2
|
||||
rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask,
|
||||
dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
|
||||
#else
|
||||
rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask,
|
||||
(PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
|
||||
#endif
|
||||
switch (rc) {
|
||||
default:
|
||||
free(dir);
|
||||
error(rc);
|
||||
return NULL;
|
||||
case NO_ERROR:
|
||||
case ERROR_NO_MORE_FILES:
|
||||
;
|
||||
}
|
||||
|
||||
dir->number = 0;
|
||||
dir->index = 0;
|
||||
dir->next = (FFBUF *)dir->ffbuf;
|
||||
|
||||
return (DIR *)dir;
|
||||
}
|
||||
|
||||
DIR *
|
||||
opendir(const char *pathname)
|
||||
{
|
||||
return openxdir(pathname, 0);
|
||||
}
|
||||
|
||||
struct dirent *
|
||||
readdir(DIR *dir)
|
||||
{
|
||||
static int dummy_ino = 2;
|
||||
|
||||
if (dir->index == dir->count) {
|
||||
Word rc;
|
||||
dir->count = 100;
|
||||
#if OS2 >= 2
|
||||
rc = DosFindNext(dir->handle, dir->ffbuf,
|
||||
sizeof dir->ffbuf, &dir->count);
|
||||
#else
|
||||
rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf,
|
||||
sizeof dir->ffbuf, &dir->count);
|
||||
#endif
|
||||
if (rc) {
|
||||
error(rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->index = 0;
|
||||
dir->next = (FFBUF *)dir->ffbuf;
|
||||
}
|
||||
|
||||
if (dir->index == dir->count)
|
||||
return NULL;
|
||||
|
||||
memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName);
|
||||
dir->entry.d_name[dir->next->cchName] = '\0';
|
||||
dir->entry.d_ino = dummy_ino++;
|
||||
dir->entry.d_reclen = dir->next->cchName;
|
||||
dir->entry.d_namlen = dir->next->cchName;
|
||||
dir->entry.d_size = dir->next->cbFile;
|
||||
dir->entry.d_attribute = dir->next->attrFile;
|
||||
dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
|
||||
dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
|
||||
|
||||
switch (dir->fstype) {
|
||||
case 'F': /* FAT */
|
||||
case 'C': /* CDFS */
|
||||
if (dir->next->attrFile & FILE_DIRECTORY)
|
||||
strupr(dir->entry.d_name);
|
||||
else
|
||||
strlwr(dir->entry.d_name);
|
||||
}
|
||||
|
||||
#if OS2 >= 2
|
||||
dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset);
|
||||
#else
|
||||
dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1);
|
||||
#endif
|
||||
++dir->number;
|
||||
++dir->index;
|
||||
|
||||
return &dir->entry;
|
||||
}
|
||||
|
||||
long
|
||||
telldir(DIR *dir)
|
||||
{
|
||||
return dir->number;
|
||||
}
|
||||
|
||||
void
|
||||
seekdir(DIR *dir, long off)
|
||||
{
|
||||
if (dir->number > off) {
|
||||
char name[MAXPATHLEN+2];
|
||||
Word rc;
|
||||
|
||||
DosFindClose(dir->handle);
|
||||
|
||||
strcpy(name, dir->name);
|
||||
strcat(name, "*");
|
||||
|
||||
dir->handle = HDIR_CREATE;
|
||||
dir->count = 32767;
|
||||
#if OS2 >= 2
|
||||
rc = DosFindFirst(name, &dir->handle, dir->attrmask,
|
||||
dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
|
||||
#else
|
||||
rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask,
|
||||
(PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
|
||||
#endif
|
||||
switch (rc) {
|
||||
default:
|
||||
error(rc);
|
||||
return;
|
||||
case NO_ERROR:
|
||||
case ERROR_NO_MORE_FILES:
|
||||
;
|
||||
}
|
||||
|
||||
dir->number = 0;
|
||||
dir->index = 0;
|
||||
dir->next = (FFBUF *)dir->ffbuf;
|
||||
}
|
||||
|
||||
while (dir->number < off && readdir(dir))
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
closedir(DIR *dir)
|
||||
{
|
||||
DosFindClose(dir->handle);
|
||||
free(dir);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
DIR *dir;
|
||||
struct dirent *ep;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
dir = opendir(argv[i]);
|
||||
if (!dir)
|
||||
continue;
|
||||
while (ep = readdir(dir))
|
||||
if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
|
||||
printf("%s%s\n", argv[i], ep->d_name);
|
||||
else
|
||||
printf("%s/%s\n", argv[i], ep->d_name);
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* OS2 */
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
#ifndef __DIRENT_H__
|
||||
#define __DIRENT_H__
|
||||
/*
|
||||
* @(#)msd_dir.h 1.4 87/11/06 Public Domain.
|
||||
*
|
||||
* A public domain implementation of BSD directory routines for
|
||||
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
|
||||
* August 1897
|
||||
*
|
||||
* Extended by Peter Lim (lim@mullian.oz) to overcome some MS DOS quirks
|
||||
* and returns 2 more pieces of information - file size & attribute.
|
||||
* Plus a little reshuffling of some #define's positions December 1987
|
||||
*
|
||||
* Some modifications by Martin Junius 02-14-89
|
||||
*
|
||||
* AK900712
|
||||
* AK910410 abs_path - make absolute path
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __EMX__
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
#if defined(__IBMC__) || defined(__IBMCPP__) || defined(XP_W32_MSVC)
|
||||
#include <stdio.h>
|
||||
#ifdef MAXPATHLEN
|
||||
#undef MAXPATHLEN
|
||||
#endif
|
||||
#define MAXPATHLEN (FILENAME_MAX*4)
|
||||
#define MAXNAMLEN FILENAME_MAX
|
||||
|
||||
#else
|
||||
#include <param.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* attribute stuff */
|
||||
#ifndef A_RONLY
|
||||
# define A_RONLY 0x01
|
||||
# define A_HIDDEN 0x02
|
||||
# define A_SYSTEM 0x04
|
||||
# define A_LABEL 0x08
|
||||
# define A_DIR 0x10
|
||||
# define A_ARCHIVE 0x20
|
||||
#endif
|
||||
|
||||
struct dirent {
|
||||
#if defined(OS2) || defined(WIN32) /* use the layout of EMX to avoid trouble */
|
||||
int d_ino; /* Dummy */
|
||||
int d_reclen; /* Dummy, same as d_namlen */
|
||||
int d_namlen; /* length of name */
|
||||
char d_name[MAXNAMLEN + 1];
|
||||
unsigned long d_size;
|
||||
unsigned short d_attribute; /* attributes (see above) */
|
||||
unsigned short d_time; /* modification time */
|
||||
unsigned short d_date; /* modification date */
|
||||
#else
|
||||
char d_name[MAXNAMLEN + 1]; /* garentee null termination */
|
||||
char d_attribute; /* .. extension .. */
|
||||
unsigned long d_size; /* .. extension .. */
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _dirdescr DIR;
|
||||
/* the structs do not have to be defined here */
|
||||
|
||||
extern DIR *opendir(const char *);
|
||||
extern DIR *openxdir(const char *, unsigned);
|
||||
extern struct dirent *readdir(DIR *);
|
||||
extern void seekdir(DIR *, long);
|
||||
extern long telldir(DIR *);
|
||||
extern void closedir(DIR *);
|
||||
#define rewinddir(dirp) seekdir(dirp, 0L)
|
||||
|
||||
extern char * abs_path(const char *name, char *buffer, int len);
|
||||
|
||||
#ifndef S_IFMT
|
||||
#define S_IFMT ( S_IFDIR | S_IFREG )
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR( m ) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG( m ) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
CORE_DEPTH = ../..
|
||||
|
||||
VPATH = $(CORE_DEPTH)/../dbm/src
|
||||
|
||||
MODULE = dbm
|
||||
|
||||
#
|
||||
# memmove.c, snprintf.c, and strerror.c are not in CSRCS because
|
||||
# the Standard C Library has memmove and strerror and DBM is not
|
||||
# using snprintf.
|
||||
#
|
||||
|
||||
CSRCS = db.c \
|
||||
h_bigkey.c \
|
||||
h_func.c \
|
||||
h_log2.c \
|
||||
h_page.c \
|
||||
hash.c \
|
||||
hash_buf.c \
|
||||
mktemp.c \
|
||||
dirent.c \
|
||||
$(NULL)
|
||||
|
||||
LIBRARY_NAME = dbm
|
||||
@@ -1,73 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
DEPTH = ../..
|
||||
CORE_DEPTH = ../..
|
||||
|
||||
VPATH = $(CORE_DEPTH)/../dbm/tests
|
||||
|
||||
MODULE = dbm
|
||||
|
||||
CSRCS = lots.c
|
||||
|
||||
PROGRAM = lots
|
||||
|
||||
include $(DEPTH)/coreconf/config.mk
|
||||
|
||||
include $(DEPTH)/dbm/config/config.mk
|
||||
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
LIBDBM = ../src/$(PLATFORM)/dbm$(STATIC_LIB_SUFFIX)
|
||||
else
|
||||
LIBDBM = ../src/$(PLATFORM)/libdbm$(STATIC_LIB_SUFFIX)
|
||||
endif
|
||||
|
||||
INCLUDES += -I$(CORE_DEPTH)/../dbm/include
|
||||
|
||||
LDFLAGS = $(LDOPTS) $(LIBDBM)
|
||||
|
||||
include $(DEPTH)/coreconf/rules.mk
|
||||
|
||||
lots.pure: lots
|
||||
purify $(CC) -o lots.pure $(CFLAGS) $(OBJS) $(MYLIBS)
|
||||
|
||||
crash: crash.o $(MYLIBS)
|
||||
$(CC) -o crash $(CFLAGS) $^
|
||||
|
||||
crash.pure: crash.o $(MYLIBS)
|
||||
purify $(CC) -o crash.pure $(CFLAGS) $^
|
||||
|
||||
@@ -1,654 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Stephen Fung <fungstep@hotmail.com> and
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include config.mk
|
||||
|
||||
# default for all platforms
|
||||
# unset this on those that have multiple freebl libraries
|
||||
FREEBL_BUILD_SINGLE_SHLIB = 1
|
||||
|
||||
ifdef USE_64
|
||||
DEFINES += -DNSS_USE_64
|
||||
endif
|
||||
|
||||
ifdef USE_ABI32_FPU
|
||||
DEFINES += -DNSS_USE_ABI32_FPU
|
||||
endif
|
||||
|
||||
ifeq ($(FREEBL_NO_DEPEND),1)
|
||||
DEFINES += -DFREEBL_NO_DEPEND
|
||||
endif
|
||||
|
||||
# FREEBL_USE_PRELINK
|
||||
#
|
||||
# Most modern version of Linux support a speed optimization scheme where an
|
||||
# application called prelink modifies programs and shared libraries to quickly
|
||||
# load if they fit into an already designed address space. In short, prelink
|
||||
# scans the list of programs and libraries on your system, assigns them a
|
||||
# predefined space in the the address space, then provides the fixups to the
|
||||
# library.
|
||||
#
|
||||
# The modification of the shared library is correctly detected by the freebl
|
||||
# FIPS checksum scheme where we check a signed hash of the library against the
|
||||
# library itself.
|
||||
#
|
||||
# The prelink command itself can reverse the process of modification and output
|
||||
# the prestine shared library as it was before prelink made it's changes.
|
||||
# This option tells Freebl could use prelink to output the original copy of
|
||||
# the shared library before prelink modified it.
|
||||
#
|
||||
# FREEBL_PRELINK_COMMAND
|
||||
#
|
||||
# This is an optional environment variable which can override the default
|
||||
# prelink command. It could be used on systems that did something similiar to
|
||||
# prelink but used a different command and syntax. The only requirement is the
|
||||
# program must take the library as the last argument, the program must output
|
||||
# the original library to standard out, and the program does not need to take
|
||||
# any quoted or imbedded spaces in its arguments (except the path to the
|
||||
# library itself, which can have imbedded spaces or special characters).
|
||||
#
|
||||
ifdef FREEBL_USE_PRELINK
|
||||
DEFINES += -DFREEBL_USE_PRELINK
|
||||
ifdef LINUX
|
||||
DEFINES += -D__GNU_SOURCE=1
|
||||
endif
|
||||
endif
|
||||
ifdef FREEBL_PRELINK_COMMAND
|
||||
DEFINES +=-DFREEBL_PRELINK_COMMAND=\"$(FREEBL_PRELINK_COMMAND)\"
|
||||
endif
|
||||
# NSS_X86 means the target is a 32-bits x86 CPU architecture
|
||||
# NSS_X64 means the target is a 64-bits x64 CPU architecture
|
||||
# NSS_X86_OR_X64 means the target is either x86 or x64
|
||||
ifeq (,$(filter-out x386 x86 x86_64,$(CPU_ARCH)))
|
||||
DEFINES += -DNSS_X86_OR_X64
|
||||
ifdef USE_64
|
||||
DEFINES += -DNSS_X64
|
||||
else
|
||||
DEFINES += -DNSS_X86
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),OSF1)
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
|
||||
MPI_SRCS += mpvalpha.c
|
||||
endif
|
||||
|
||||
ifeq (OS2,$(OS_TARGET))
|
||||
ASFILES = mpi_x86_os2.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) #omits WINCE
|
||||
ifndef USE_64
|
||||
# 32-bit Windows
|
||||
ifdef NS_USE_GCC
|
||||
# Ideally, we want to use assembler
|
||||
# ASFILES = mpi_x86.s
|
||||
# DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE \
|
||||
# -DMP_ASSEMBLY_DIV_2DX1D
|
||||
# but we haven't figured out how to make it work, so we are not
|
||||
# using assembler right now.
|
||||
ASFILES =
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT
|
||||
else
|
||||
# MSVC
|
||||
MPI_SRCS += mpi_x86_asm.c
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER += -Ox # maximum optimization for freebl
|
||||
endif
|
||||
endif
|
||||
else
|
||||
# -DMP_NO_MP_WORD
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER += -Ox # maximum optimization for freebl
|
||||
endif
|
||||
ASFILES = arcfour-amd64-masm.asm mpi_amd64_masm.asm mp_comba_amd64_masm.asm
|
||||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
MPI_SRCS += mpi_amd64.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DMP_ARGCHK=0 # no assert in WinCE
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),IRIX)
|
||||
ifeq ($(USE_N32),1)
|
||||
ASFILES = mpi_mips.s
|
||||
ifeq ($(NS_USE_GCC),1)
|
||||
ASFLAGS = -Wp,-P -Wp,-traditional -O -mips3
|
||||
else
|
||||
ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3
|
||||
endif
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
ifeq ($(CPU_ARCH),x86_64)
|
||||
ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s
|
||||
ASFLAGS += -march=opteron -m64 -fPIC -Wa,--noexecstack
|
||||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# DEFINES += -DMPI_AMD64_ADD
|
||||
# comment the next two lines to turn off intel HW accelleration
|
||||
# DEFINES += -DUSE_HW_AES
|
||||
# ASFILES += intel-aes.s
|
||||
MPI_SRCS += mpi_amd64.c mp_comba.c
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ASFILES = mpi_x86.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# The floating point ECC code doesn't work on Linux x86 (bug 311432).
|
||||
#ECL_USE_FP = 1
|
||||
endif
|
||||
endif # Linux
|
||||
|
||||
ifeq ($(OS_TARGET),AIX)
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
ifndef USE_64
|
||||
DEFINES += -DMP_NO_DIV_WORD -DMP_NO_ADD_WORD -DMP_NO_SUB_WORD
|
||||
endif
|
||||
endif # AIX
|
||||
|
||||
ifeq ($(OS_TARGET), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
# PA-RISC
|
||||
ASFILES += ret_cr16.s
|
||||
ifndef USE_64
|
||||
FREEBL_BUILD_SINGLE_SHLIB =
|
||||
HAVE_ABI32_INT32 = 1
|
||||
HAVE_ABI32_FPU = 1
|
||||
endif
|
||||
ifdef FREEBL_CHILD_BUILD
|
||||
ifdef USE_ABI32_INT32
|
||||
# build for DA1.1 (HP PA 1.1) 32-bit ABI build with 32-bit arithmetic
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
else
|
||||
ifdef USE_64
|
||||
# this builds for DA2.0W (HP PA 2.0 Wide), the LP64 ABI, using 64-bit digits
|
||||
MPI_SRCS += mpi_hp.c
|
||||
ASFILES += hpma512.s hppa20.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
else
|
||||
# this builds for DA2.0 (HP PA 2.0 Narrow) ABI32_FPU model
|
||||
# (the 32-bit ABI with 64-bit registers) using 64-bit digits
|
||||
MPI_SRCS += mpi_hp.c
|
||||
ASFILES += hpma512.s hppa20.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
ifndef NS_USE_GCC
|
||||
ARCHFLAG = -Aa +e +DA2.0 +DS2.0
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# The blapi functions are defined not only in the freebl shared
|
||||
# libraries but also in the shared libraries linked with loader.c
|
||||
# (libsoftokn3.so and libssl3.so). We need to use GNU ld's
|
||||
# -Bsymbolic option or the equivalent option for other linkers
|
||||
# to bind the blapi function references in FREEBLVector vector
|
||||
# (ldvector.c) to the blapi functions defined in the freebl
|
||||
# shared libraries.
|
||||
ifeq (,$(filter-out BSD_OS FreeBSD Linux NetBSD OpenBSD, $(OS_TARGET)))
|
||||
MKSHLIB += -Wl,-Bsymbolic
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
ifdef GCC_USE_GNU_LD
|
||||
MKSHLIB += -Wl,-Bsymbolic,-z,now,-z,text
|
||||
else
|
||||
MKSHLIB += -Wl,-B,symbolic,-z,now,-z,text
|
||||
endif # GCC_USE_GNU_LD
|
||||
else
|
||||
MKSHLIB += -B symbolic -z now -z text
|
||||
endif # NS_USE_GCC
|
||||
|
||||
# Sun's WorkShop defines v8, v8plus and v9 architectures.
|
||||
# gcc on Solaris defines v8 and v9 "cpus".
|
||||
# gcc's v9 is equivalent to Workshop's v8plus.
|
||||
# gcc's -m64 is equivalent to Workshop's v9
|
||||
# We always use Sun's assembler, which uses Sun's naming convention.
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
FREEBL_BUILD_SINGLE_SHLIB=
|
||||
ifdef USE_64
|
||||
HAVE_ABI64_INT = 1
|
||||
HAVE_ABI64_FPU = 1
|
||||
else
|
||||
HAVE_ABI32_INT32 = 1
|
||||
HAVE_ABI32_FPU = 1
|
||||
HAVE_ABI32_INT64 = 1
|
||||
endif
|
||||
SYSV_SPARC = 1
|
||||
SOLARIS_AS = /usr/ccs/bin/as
|
||||
#### set arch, asm, c flags
|
||||
ifdef NS_USE_GCC
|
||||
ifdef USE_ABI32_INT32
|
||||
# default ARCHFLAG=-mcpu=v8 set by coreconf/sunOS5.mk
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
ARCHFLAG=-mcpu=v9 -Wa,-xarch=v8plus
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC
|
||||
endif
|
||||
ifdef USE_ABI32_FPU
|
||||
ARCHFLAG=-mcpu=v9 -Wa,-xarch=v8plusa
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
|
||||
endif # USE_ABI32_FPU
|
||||
ifdef USE_ABI64_INT
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
ARCHFLAG += -mcpu=v9 -Wa,-xarch=v9
|
||||
SOLARIS_AS_FLAGS = -xarch=v9 -K PIC
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# It uses floating point, and 32-bit word size
|
||||
ARCHFLAG += -mcpu=v9 -Wa,-xarch=v9a
|
||||
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
|
||||
endif
|
||||
else # NS_USE_GCC
|
||||
# FPU_TARGET_OPTIMIZER specifies the target processor and cache
|
||||
# properties of the ABI32_FPU and ABI64_FPU architectures for use
|
||||
# by the optimizer.
|
||||
ifeq (,$(findstring Sun WorkShop 6,$(shell $(CC) -V 2>&1)))
|
||||
# if the compiler is not Forte 6
|
||||
FPU_TARGET_OPTIMIZER = -xcache=64/32/4:1024/64/4 -xchip=ultra3
|
||||
else
|
||||
# Forte 6 C compiler generates incorrect code for rijndael.c
|
||||
# if -xchip=ultra3 is used (Bugzilla bug 333925). So we revert
|
||||
# to what we used in NSS 3.10.
|
||||
FPU_TARGET_OPTIMIZER = -xchip=ultra2
|
||||
endif
|
||||
ifdef USE_ABI32_INT32
|
||||
#ARCHFLAG=-xarch=v8 set in coreconf/sunOS5.mk
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
|
||||
# 32-bit ABI, it uses 64-bit words, integer arithmetic,
|
||||
# no FPU (non-VIS cpus).
|
||||
# These flags were suggested by the compiler group for building
|
||||
# with SunStudio 10.
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -xO4
|
||||
endif
|
||||
SOL_CFLAGS += -xtarget=generic
|
||||
ARCHFLAG = -xarch=v8plus
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC
|
||||
endif
|
||||
ifdef USE_ABI32_FPU
|
||||
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
|
||||
# 32-bit ABI, it uses FPU code, and 32-bit word size.
|
||||
# these flags were determined by running cc -### -fast and copying
|
||||
# the generated flag settings
|
||||
SOL_CFLAGS += -fsingle -xmemalign=8s
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fsimple=1
|
||||
SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
|
||||
SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
|
||||
SOL_CFLAGS += -xlibmil -xO5
|
||||
endif
|
||||
ARCHFLAG = -xarch=v8plusa
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
|
||||
endif
|
||||
ifdef USE_ABI64_INT
|
||||
# this builds for Sparc v9a pure 64-bit architecture,
|
||||
# no FPU (non-VIS cpus). For building with SunStudio 10.
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -xO4
|
||||
endif
|
||||
SOL_CFLAGS += -xtarget=generic
|
||||
ARCHFLAG = -xarch=v9
|
||||
SOLARIS_AS_FLAGS = -xarch=v9 -K PIC
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# It uses floating point, and 32-bit word size.
|
||||
# See comment for USE_ABI32_FPU.
|
||||
SOL_CFLAGS += -fsingle -xmemalign=8s
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fsimple=1
|
||||
SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
|
||||
SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
|
||||
SOL_CFLAGS += -xlibmil -xO5
|
||||
endif
|
||||
ARCHFLAG = -xarch=v9a
|
||||
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
|
||||
endif
|
||||
endif # NS_USE_GCC
|
||||
|
||||
### set flags for both GCC and Sun cc
|
||||
ifdef USE_ABI32_INT32
|
||||
# this builds for Sparc v8 pure 32-bit architecture
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
|
||||
ASFILES = mpv_sparcv8x.s
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
|
||||
# 32-bit ABI, it uses 64-bit words, integer arithmetic, no FPU
|
||||
# best times are with no MP_ flags specified
|
||||
endif
|
||||
ifdef USE_ABI32_FPU
|
||||
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
|
||||
# 32-bit ABI, it uses FPU code, and 32-bit word size
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv8.s montmulfv8.s
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
|
||||
ECL_USE_FP = 1
|
||||
endif
|
||||
ifdef USE_ABI64_INT
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# best times are with no MP_ flags specified
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# It uses floating point, and 32-bit word size
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv9.s montmulfv9.s
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
|
||||
ECL_USE_FP = 1
|
||||
endif
|
||||
|
||||
else
|
||||
# Solaris for non-sparc family CPUs
|
||||
ifdef NS_USE_GCC
|
||||
LD = gcc
|
||||
AS = gcc
|
||||
ASFLAGS = -x assembler-with-cpp
|
||||
endif
|
||||
ifeq ($(USE_64),1)
|
||||
# Solaris for AMD64
|
||||
ifdef NS_USE_GCC
|
||||
ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s
|
||||
ASFLAGS += -march=opteron -m64 -fPIC
|
||||
MPI_SRCS += mp_comba.c
|
||||
else
|
||||
ASFILES = arcfour-amd64-sun.s mpi_amd64_sun.s sha-fast-amd64-sun.s
|
||||
ASFILES += mp_comba_amd64_sun.s mpcpucache_amd64.s
|
||||
ASFLAGS += -xarch=generic64 -K PIC
|
||||
SOL_CFLAGS += -xprefetch=no
|
||||
SHA_SRCS =
|
||||
MPCPU_SRCS =
|
||||
endif
|
||||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# comment the next two lines to turn off intel HW accelleration
|
||||
# DEFINES += -DUSE_HW_AES
|
||||
# ASFILES += intel-aes.s
|
||||
MPI_SRCS += mpi_amd64.c
|
||||
else
|
||||
# Solaris x86
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
|
||||
ASFILES = mpi_i86pc.s
|
||||
ifndef NS_USE_GCC
|
||||
MPCPU_SRCS =
|
||||
ASFILES += mpcpucache_x86.s
|
||||
endif
|
||||
endif
|
||||
endif # Solaris for non-sparc family CPUs
|
||||
endif # target == SunOS
|
||||
|
||||
ifdef NSS_ENABLE_ECC
|
||||
ifdef ECL_USE_FP
|
||||
#enable floating point ECC code
|
||||
DEFINES += -DECL_USE_FP
|
||||
ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c
|
||||
ECL_HDRS += ecp_fp.h
|
||||
endif
|
||||
endif # NSS_ENABLE_ECC
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
export:: private_export
|
||||
|
||||
rijndael_tables:
|
||||
$(CC) -o $(OBJDIR)/make_rijndael_tab rijndael_tables.c \
|
||||
$(DEFINES) $(INCLUDES) $(OBJDIR)/libfreebl.a
|
||||
$(OBJDIR)/make_rijndael_tab
|
||||
|
||||
vpath %.h mpi ecl
|
||||
vpath %.c mpi ecl
|
||||
vpath %.S mpi ecl
|
||||
vpath %.s mpi ecl
|
||||
vpath %.asm mpi ecl
|
||||
INCLUDES += -Impi -Iecl
|
||||
|
||||
|
||||
DEFINES += -DMP_API_COMPATIBLE
|
||||
|
||||
MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c
|
||||
|
||||
MPI_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_SRCS:.c=$(OBJ_SUFFIX)))
|
||||
MPI_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_USERS:.c=$(OBJ_SUFFIX)))
|
||||
|
||||
$(MPI_OBJS): $(MPI_HDRS)
|
||||
|
||||
ECL_USERS = ec.c
|
||||
|
||||
ECL_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_SRCS:.c=$(OBJ_SUFFIX)) $(ECL_ASM_SRCS:$(ASM_SUFFIX)=$(OBJ_SUFFIX)))
|
||||
ECL_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_USERS:.c=$(OBJ_SUFFIX)))
|
||||
|
||||
$(ECL_OBJS): $(ECL_HDRS)
|
||||
|
||||
|
||||
|
||||
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c os2_rand.c
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c
|
||||
|
||||
$(OBJDIR)/ldvector$(OBJ_SUFFIX) $(OBJDIR)/loader$(OBJ_SUFFIX) : loader.h
|
||||
|
||||
ifeq ($(SYSV_SPARC),1)
|
||||
|
||||
$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/mpv_sparcv8x.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpv_sparcv9.o $(OBJDIR)/montmulfv9.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpmontg.o: mpmontg.c montmulf.h
|
||||
|
||||
endif
|
||||
|
||||
ifndef FREEBL_CHILD_BUILD
|
||||
|
||||
# Parent build. This is where we decide which shared libraries to build
|
||||
|
||||
ifdef FREEBL_BUILD_SINGLE_SHLIB
|
||||
|
||||
################### Single shared lib stuff #########################
|
||||
SINGLE_SHLIB_DIR = $(OBJDIR)/$(OS_TARGET)_SINGLE_SHLIB
|
||||
ALL_TRASH += $(SINGLE_SHLIB_DIR)
|
||||
|
||||
$(SINGLE_SHLIB_DIR):
|
||||
-mkdir $(SINGLE_SHLIB_DIR)
|
||||
|
||||
release_md libs:: $(SINGLE_SHLIB_DIR)
|
||||
$(MAKE) FREEBL_CHILD_BUILD=1 \
|
||||
OBJDIR=$(SINGLE_SHLIB_DIR) $@
|
||||
######################## common stuff #########################
|
||||
|
||||
endif
|
||||
|
||||
# multiple shared libraries
|
||||
|
||||
######################## ABI32_FPU stuff #########################
|
||||
ifdef HAVE_ABI32_FPU
|
||||
ABI32_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_FPU
|
||||
ALL_TRASH += $(ABI32_FPU_DIR)
|
||||
|
||||
$(ABI32_FPU_DIR):
|
||||
-mkdir $(ABI32_FPU_DIR)
|
||||
|
||||
release_md libs:: $(ABI32_FPU_DIR)
|
||||
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_FPU=1 \
|
||||
OBJDIR=$(ABI32_FPU_DIR) $@
|
||||
endif
|
||||
|
||||
######################## ABI32_INT32 stuff #########################
|
||||
ifdef HAVE_ABI32_INT32
|
||||
ABI32_INT32_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_INT32
|
||||
ALL_TRASH += $(ABI32_INT32_DIR)
|
||||
|
||||
$(ABI32_INT32_DIR):
|
||||
-mkdir $(ABI32_INT32_DIR)
|
||||
|
||||
release_md libs:: $(ABI32_INT32_DIR)
|
||||
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_INT32=1 \
|
||||
OBJDIR=$(ABI32_INT32_DIR) $@
|
||||
endif
|
||||
|
||||
######################## ABI32_INT64 stuff #########################
|
||||
ifdef HAVE_ABI32_INT64
|
||||
ABI32_INT64_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_INT64
|
||||
ALL_TRASH += $(ABI32_INT64_DIR)
|
||||
|
||||
$(ABI32_INT64_DIR):
|
||||
-mkdir $(ABI32_INT64_DIR)
|
||||
|
||||
release_md libs:: $(ABI32_INT64_DIR)
|
||||
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_INT64=1\
|
||||
OBJDIR=$(ABI32_INT64_DIR) $@
|
||||
endif
|
||||
|
||||
######################## END of 32-bit stuff #########################
|
||||
|
||||
# above is 32-bit builds, below is 64-bit builds
|
||||
|
||||
######################## ABI64_FPU stuff #########################
|
||||
ifdef HAVE_ABI64_FPU
|
||||
ABI64_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI64_FPU
|
||||
ALL_TRASH += $(ABI64_FPU_DIR)
|
||||
|
||||
$(ABI64_FPU_DIR):
|
||||
-mkdir $(ABI64_FPU_DIR)
|
||||
|
||||
release_md libs:: $(ABI64_FPU_DIR)
|
||||
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI64_FPU=1 \
|
||||
OBJDIR=$(ABI64_FPU_DIR) $@
|
||||
endif
|
||||
|
||||
######################## ABI64_INT stuff #########################
|
||||
ifdef HAVE_ABI64_INT
|
||||
ABI64_INT_DIR = $(OBJDIR)/$(OS_TARGET)_ABI64_INT
|
||||
ALL_TRASH += $(ABI64_INT_DIR)
|
||||
|
||||
$(ABI64_INT_DIR):
|
||||
-mkdir $(ABI64_INT_DIR)
|
||||
|
||||
release_md libs:: $(ABI64_INT_DIR)
|
||||
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI64_INT=1 \
|
||||
OBJDIR=$(ABI64_INT_DIR) $@
|
||||
endif
|
||||
|
||||
endif # FREEBL_CHILD_BUILD
|
||||
|
||||
|
||||
# Bugzilla Bug 333917: the non-x86 code in desblapi.c seems to violate
|
||||
# ANSI C's strict aliasing rules.
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
ifneq ($(CPU_ARCH),x86)
|
||||
$(OBJDIR)/$(PROG_PREFIX)desblapi$(OBJ_SUFFIX): desblapi.c
|
||||
@$(MAKE_OBJDIR)
|
||||
ifdef NEED_ABSOLUTE_PATH
|
||||
$(CC) -o $@ -c $(CFLAGS) -fno-strict-aliasing $(call core_abspath,$<)
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) -fno-strict-aliasing $<
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,417 +0,0 @@
|
||||
/*
|
||||
* aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: aeskeywrap.c,v 1.5 2008-11-18 19:48:21 rrelyea%redhat.com Exp $ */
|
||||
|
||||
/* $Id: aeskeywrap.c,v 1.5 2008-11-18 19:48:21 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "prcpucfg.h"
|
||||
#if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
|
||||
#else
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
|
||||
#endif
|
||||
#include "prtypes.h" /* for PRUintXX */
|
||||
#include "secport.h" /* for PORT_XXX */
|
||||
#include "secerr.h"
|
||||
#include "blapi.h" /* for AES_ functions */
|
||||
#include "rijndael.h"
|
||||
|
||||
struct AESKeyWrapContextStr {
|
||||
unsigned char iv[AES_KEY_WRAP_IV_BYTES];
|
||||
AESContext aescx;
|
||||
};
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** AES key wrap algorithm, RFC 3394
|
||||
*/
|
||||
|
||||
AESKeyWrapContext *
|
||||
AESKeyWrap_AllocateContext(void)
|
||||
{
|
||||
AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext);
|
||||
return cx;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
AESKeyWrap_InitContext(AESKeyWrapContext *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int x1,
|
||||
unsigned int encrypt,
|
||||
unsigned int x2)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
if (!cx) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (iv) {
|
||||
memcpy(cx->iv, iv, sizeof cx->iv);
|
||||
} else {
|
||||
memset(cx->iv, 0xA6, sizeof cx->iv);
|
||||
}
|
||||
rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
|
||||
AES_BLOCK_SIZE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new AES context suitable for AES encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "keylen" the number of bytes of key data (16, 24, or 32)
|
||||
*/
|
||||
extern AESKeyWrapContext *
|
||||
AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
|
||||
int encrypt, unsigned int keylen)
|
||||
{
|
||||
SECStatus rv;
|
||||
AESKeyWrapContext * cx = AESKeyWrap_AllocateContext();
|
||||
if (!cx)
|
||||
return NULL; /* error is already set */
|
||||
rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_Free(cx);
|
||||
cx = NULL; /* error should already be set */
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy a AES KeyWrap context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void
|
||||
AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
AES_DestroyContext(&cx->aescx, PR_FALSE);
|
||||
/* memset(cx, 0, sizeof *cx); */
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
#if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
|
||||
/* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
|
||||
** (Most significant byte first) in memory. The only ALU operations done
|
||||
** on them are increment, decrement, and XOR. So, on little-endian CPUs,
|
||||
** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
|
||||
** are simulated in the following code. This is thought to be faster and
|
||||
** simpler than trying to convert the data to little-endian and back.
|
||||
*/
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function increments the 64-bit value T, and then
|
||||
** XORs it with A, changing A.
|
||||
*/
|
||||
static void
|
||||
increment_and_xor(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
if (!++T[7])
|
||||
if (!++T[6])
|
||||
if (!++T[5])
|
||||
if (!++T[4])
|
||||
if (!++T[3])
|
||||
if (!++T[2])
|
||||
if (!++T[1])
|
||||
++T[0];
|
||||
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
}
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function XORs T with A, giving a new A, then
|
||||
** decrements the 64-bit value T.
|
||||
*/
|
||||
static void
|
||||
xor_and_decrement(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
|
||||
if (!T[7]--)
|
||||
if (!T[6]--)
|
||||
if (!T[5]--)
|
||||
if (!T[4]--)
|
||||
if (!T[3]--)
|
||||
if (!T[2]--)
|
||||
if (!T[1]--)
|
||||
T[0]--;
|
||||
|
||||
}
|
||||
|
||||
/* Given an unsigned long t (in host byte order), store this value as a
|
||||
** 64-bit big-endian value (MSB first) in *pt.
|
||||
*/
|
||||
static void
|
||||
set_t(unsigned char *pt, unsigned long t)
|
||||
{
|
||||
pt[7] = (unsigned char)t; t >>= 8;
|
||||
pt[6] = (unsigned char)t; t >>= 8;
|
||||
pt[5] = (unsigned char)t; t >>= 8;
|
||||
pt[4] = (unsigned char)t; t >>= 8;
|
||||
pt[3] = (unsigned char)t; t >>= 8;
|
||||
pt[2] = (unsigned char)t; t >>= 8;
|
||||
pt[1] = (unsigned char)t; t >>= 8;
|
||||
pt[0] = (unsigned char)t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform AES key wrap.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
extern SECStatus
|
||||
AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks + 1);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
memcpy(&R[1], input, inputLen);
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 0;
|
||||
#else
|
||||
memset(&t, 0, sizeof t);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = 1; i <= nBlocks; ++i) {
|
||||
B[1] = R[i];
|
||||
s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
/* here, increment t and XOR A with t (in big endian order); */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= ++t;
|
||||
#else
|
||||
increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
R[0] = A;
|
||||
memcpy(output, &R[0], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, outLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
|
||||
/*
|
||||
** Perform AES key unwrap.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
extern SECStatus
|
||||
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
|
||||
0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
nBlocks--;
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&R[0], input, inputLen);
|
||||
A = R[0];
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 6UL * nBlocks;
|
||||
#else
|
||||
set_t((unsigned char *)&t, 6UL * nBlocks);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = nBlocks; i; --i) {
|
||||
/* here, XOR A with t (in big endian order) and decrement t; */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= t--;
|
||||
#else
|
||||
xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
B[1] = R[i];
|
||||
s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
if (!bad) {
|
||||
memcpy(output, &R[1], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else {
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, inputLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
@@ -1,519 +0,0 @@
|
||||
/*
|
||||
* alg2268.c - implementation of the algorithm in RFC 2268
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* $Id: alg2268.c,v 1.9 2009-04-09 22:11:07 julien.pierre.boogz%sun.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
#ifdef XP_UNIX_XXX
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** RC2 symmetric block cypher
|
||||
*/
|
||||
|
||||
typedef SECStatus (rc2Func)(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* forward declarations */
|
||||
static rc2Func rc2_EncryptECB;
|
||||
static rc2Func rc2_DecryptECB;
|
||||
static rc2Func rc2_EncryptCBC;
|
||||
static rc2Func rc2_DecryptCBC;
|
||||
|
||||
typedef union {
|
||||
PRUint32 l[2];
|
||||
PRUint16 s[4];
|
||||
PRUint8 b[8];
|
||||
} RC2Block;
|
||||
|
||||
struct RC2ContextStr {
|
||||
union {
|
||||
PRUint8 Kb[128];
|
||||
PRUint16 Kw[64];
|
||||
} u;
|
||||
RC2Block iv;
|
||||
rc2Func *enc;
|
||||
rc2Func *dec;
|
||||
};
|
||||
|
||||
#define B u.Kb
|
||||
#define K u.Kw
|
||||
#define BYTESWAP(x) ((x) << 8 | (x) >> 8)
|
||||
#define SWAPK(i) cx->K[i] = (tmpS = cx->K[i], BYTESWAP(tmpS))
|
||||
#define RC2_BLOCK_SIZE 8
|
||||
|
||||
#define LOAD_HARD(R) \
|
||||
R[0] = (PRUint16)input[1] << 8 | input[0]; \
|
||||
R[1] = (PRUint16)input[3] << 8 | input[2]; \
|
||||
R[2] = (PRUint16)input[5] << 8 | input[4]; \
|
||||
R[3] = (PRUint16)input[7] << 8 | input[6];
|
||||
#define LOAD_EASY(R) \
|
||||
R[0] = ((PRUint16 *)input)[0]; \
|
||||
R[1] = ((PRUint16 *)input)[1]; \
|
||||
R[2] = ((PRUint16 *)input)[2]; \
|
||||
R[3] = ((PRUint16 *)input)[3];
|
||||
#define STORE_HARD(R) \
|
||||
output[0] = (PRUint8)(R[0]); output[1] = (PRUint8)(R[0] >> 8); \
|
||||
output[2] = (PRUint8)(R[1]); output[3] = (PRUint8)(R[1] >> 8); \
|
||||
output[4] = (PRUint8)(R[2]); output[5] = (PRUint8)(R[2] >> 8); \
|
||||
output[6] = (PRUint8)(R[3]); output[7] = (PRUint8)(R[3] >> 8);
|
||||
#define STORE_EASY(R) \
|
||||
((PRUint16 *)output)[0] = R[0]; \
|
||||
((PRUint16 *)output)[1] = R[1]; \
|
||||
((PRUint16 *)output)[2] = R[2]; \
|
||||
((PRUint16 *)output)[3] = R[3];
|
||||
|
||||
#if defined (NSS_X86_OR_X64)
|
||||
#define LOAD(R) LOAD_EASY(R)
|
||||
#define STORE(R) STORE_EASY(R)
|
||||
#elif !defined(IS_LITTLE_ENDIAN)
|
||||
#define LOAD(R) LOAD_HARD(R)
|
||||
#define STORE(R) STORE_HARD(R)
|
||||
#else
|
||||
#define LOAD(R) if ((ptrdiff_t)input & 1) { LOAD_HARD(R) } else { LOAD_EASY(R) }
|
||||
#define STORE(R) if ((ptrdiff_t)input & 1) { STORE_HARD(R) } else { STORE_EASY(R) }
|
||||
#endif
|
||||
|
||||
static const PRUint8 S[256] = {
|
||||
0331,0170,0371,0304,0031,0335,0265,0355,0050,0351,0375,0171,0112,0240,0330,0235,
|
||||
0306,0176,0067,0203,0053,0166,0123,0216,0142,0114,0144,0210,0104,0213,0373,0242,
|
||||
0027,0232,0131,0365,0207,0263,0117,0023,0141,0105,0155,0215,0011,0201,0175,0062,
|
||||
0275,0217,0100,0353,0206,0267,0173,0013,0360,0225,0041,0042,0134,0153,0116,0202,
|
||||
0124,0326,0145,0223,0316,0140,0262,0034,0163,0126,0300,0024,0247,0214,0361,0334,
|
||||
0022,0165,0312,0037,0073,0276,0344,0321,0102,0075,0324,0060,0243,0074,0266,0046,
|
||||
0157,0277,0016,0332,0106,0151,0007,0127,0047,0362,0035,0233,0274,0224,0103,0003,
|
||||
0370,0021,0307,0366,0220,0357,0076,0347,0006,0303,0325,0057,0310,0146,0036,0327,
|
||||
0010,0350,0352,0336,0200,0122,0356,0367,0204,0252,0162,0254,0065,0115,0152,0052,
|
||||
0226,0032,0322,0161,0132,0025,0111,0164,0113,0237,0320,0136,0004,0030,0244,0354,
|
||||
0302,0340,0101,0156,0017,0121,0313,0314,0044,0221,0257,0120,0241,0364,0160,0071,
|
||||
0231,0174,0072,0205,0043,0270,0264,0172,0374,0002,0066,0133,0045,0125,0227,0061,
|
||||
0055,0135,0372,0230,0343,0212,0222,0256,0005,0337,0051,0020,0147,0154,0272,0311,
|
||||
0323,0000,0346,0317,0341,0236,0250,0054,0143,0026,0001,0077,0130,0342,0211,0251,
|
||||
0015,0070,0064,0033,0253,0063,0377,0260,0273,0110,0014,0137,0271,0261,0315,0056,
|
||||
0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255
|
||||
};
|
||||
|
||||
RC2Context * RC2_AllocateContext(void)
|
||||
{
|
||||
return PORT_ZNew(RC2Context);
|
||||
}
|
||||
SECStatus
|
||||
RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len,
|
||||
const unsigned char *input, int mode, unsigned int efLen8,
|
||||
unsigned int unused)
|
||||
{
|
||||
PRUint8 *L,*L2;
|
||||
int i;
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
PRUint16 tmpS;
|
||||
#endif
|
||||
PRUint8 tmpB;
|
||||
|
||||
if (!key || !cx || !len || len > (sizeof cx->B) ||
|
||||
efLen8 > (sizeof cx->B)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (mode == NSS_RC2) {
|
||||
/* groovy */
|
||||
} else if (mode == NSS_RC2_CBC) {
|
||||
if (!input) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (mode == NSS_RC2_CBC) {
|
||||
cx->enc = & rc2_EncryptCBC;
|
||||
cx->dec = & rc2_DecryptCBC;
|
||||
LOAD(cx->iv.s);
|
||||
} else {
|
||||
cx->enc = & rc2_EncryptECB;
|
||||
cx->dec = & rc2_DecryptECB;
|
||||
}
|
||||
|
||||
/* Step 0. Copy key into table. */
|
||||
memcpy(cx->B, key, len);
|
||||
|
||||
/* Step 1. Compute all values to the right of the key. */
|
||||
L2 = cx->B;
|
||||
L = L2 + len;
|
||||
tmpB = L[-1];
|
||||
for (i = (sizeof cx->B) - len; i > 0; --i) {
|
||||
*L++ = tmpB = S[ (PRUint8)(tmpB + *L2++) ];
|
||||
}
|
||||
|
||||
/* step 2. Adjust left most byte of effective key. */
|
||||
i = (sizeof cx->B) - efLen8;
|
||||
L = cx->B + i;
|
||||
*L = tmpB = S[*L]; /* mask is always 0xff */
|
||||
|
||||
/* step 3. Recompute all values to the left of effective key. */
|
||||
L2 = --L + efLen8;
|
||||
while(L >= cx->B) {
|
||||
*L-- = tmpB = S[ tmpB ^ *L2-- ];
|
||||
}
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
for (i = 63; i >= 0; --i) {
|
||||
SWAPK(i); /* candidate for unrolling */
|
||||
}
|
||||
#endif
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new RC2 context suitable for RC2 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC)
|
||||
** "mode" one of NSS_RC2 or NSS_RC2_CBC
|
||||
** "effectiveKeyLen" in bytes, not bits.
|
||||
**
|
||||
** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC2Context *
|
||||
RC2_CreateContext(const unsigned char *key, unsigned int len,
|
||||
const unsigned char *iv, int mode, unsigned efLen8)
|
||||
{
|
||||
RC2Context *cx = PORT_ZNew(RC2Context);
|
||||
if (cx) {
|
||||
SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0);
|
||||
if (rv != SECSuccess) {
|
||||
RC2_DestroyContext(cx, PR_TRUE);
|
||||
cx = NULL;
|
||||
}
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC2 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC2_DestroyContext(RC2Context *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit) {
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ROL(x,k) (x << k | x >> (16-k))
|
||||
#define MIX(j) \
|
||||
R0 = R0 + cx->K[ 4*j+0] + (R3 & R2) + (~R3 & R1); R0 = ROL(R0,1);\
|
||||
R1 = R1 + cx->K[ 4*j+1] + (R0 & R3) + (~R0 & R2); R1 = ROL(R1,2);\
|
||||
R2 = R2 + cx->K[ 4*j+2] + (R1 & R0) + (~R1 & R3); R2 = ROL(R2,3);\
|
||||
R3 = R3 + cx->K[ 4*j+3] + (R2 & R1) + (~R2 & R0); R3 = ROL(R3,5)
|
||||
#define MASH \
|
||||
R0 = R0 + cx->K[R3 & 63];\
|
||||
R1 = R1 + cx->K[R0 & 63];\
|
||||
R2 = R2 + cx->K[R1 & 63];\
|
||||
R3 = R3 + cx->K[R2 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Encrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 0 */
|
||||
/* step 4. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(0);
|
||||
MIX(1);
|
||||
MIX(2);
|
||||
MIX(3);
|
||||
MIX(4);
|
||||
|
||||
/* step 5. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 6. Perform 6 mixing rounds. */
|
||||
|
||||
MIX(5);
|
||||
MIX(6);
|
||||
MIX(7);
|
||||
MIX(8);
|
||||
MIX(9);
|
||||
MIX(10);
|
||||
|
||||
/* step 7. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 8. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(11);
|
||||
MIX(12);
|
||||
MIX(13);
|
||||
MIX(14);
|
||||
MIX(15);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
#define ROR(x,k) (x >> k | x << (16-k))
|
||||
#define R_MIX(j) \
|
||||
R3 = ROR(R3,5); R3 = R3 - cx->K[ 4*j+3] - (R2 & R1) - (~R2 & R0); \
|
||||
R2 = ROR(R2,3); R2 = R2 - cx->K[ 4*j+2] - (R1 & R0) - (~R1 & R3); \
|
||||
R1 = ROR(R1,2); R1 = R1 - cx->K[ 4*j+1] - (R0 & R3) - (~R0 & R2); \
|
||||
R0 = ROR(R0,1); R0 = R0 - cx->K[ 4*j+0] - (R3 & R2) - (~R3 & R1)
|
||||
#define R_MASH \
|
||||
R3 = R3 - cx->K[R2 & 63];\
|
||||
R2 = R2 - cx->K[R1 & 63];\
|
||||
R1 = R1 - cx->K[R0 & 63];\
|
||||
R0 = R0 - cx->K[R3 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Decrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 63 */
|
||||
/* step 4. Perform 5 r_mixing rounds. */
|
||||
R_MIX(15);
|
||||
R_MIX(14);
|
||||
R_MIX(13);
|
||||
R_MIX(12);
|
||||
R_MIX(11);
|
||||
|
||||
/* step 5. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 6. Perform 6 r_mixing rounds. */
|
||||
R_MIX(10);
|
||||
R_MIX(9);
|
||||
R_MIX(8);
|
||||
R_MIX(7);
|
||||
R_MIX(6);
|
||||
R_MIX(5);
|
||||
|
||||
/* step 7. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 8. Perform 5 r_mixing rounds. */
|
||||
R_MIX(4);
|
||||
R_MIX(3);
|
||||
R_MIX(2);
|
||||
R_MIX(1);
|
||||
R_MIX(0);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
|
||||
LOAD(iBlock.s)
|
||||
iBlock.l[0] ^= cx->iv.l[0];
|
||||
iBlock.l[1] ^= cx->iv.l[1];
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
cx->iv = iBlock;
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
RC2Block oBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &oBlock, &iBlock);
|
||||
oBlock.l[0] ^= cx->iv.l[0];
|
||||
oBlock.l[1] ^= cx->iv.l[1];
|
||||
cx->iv = iBlock;
|
||||
STORE(oBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Perform RC2 encryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus RC2_Encrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->enc)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC2 decryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->dec)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "secport.h"
|
||||
#include "hasht.h"
|
||||
#include "blapit.h"
|
||||
#include "alghmac.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#define HMAC_PAD_SIZE HASH_BLOCK_LENGTH_MAX
|
||||
|
||||
struct HMACContextStr {
|
||||
void *hash;
|
||||
const SECHashObject *hashobj;
|
||||
PRBool wasAllocated;
|
||||
unsigned char ipad[HMAC_PAD_SIZE];
|
||||
unsigned char opad[HMAC_PAD_SIZE];
|
||||
};
|
||||
|
||||
void
|
||||
HMAC_Destroy(HMACContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx == NULL)
|
||||
return;
|
||||
|
||||
PORT_Assert(!freeit == !cx->wasAllocated);
|
||||
if (cx->hash != NULL) {
|
||||
cx->hashobj->destroy(cx->hash, PR_TRUE);
|
||||
PORT_Memset(cx, 0, sizeof *cx);
|
||||
}
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
HMAC_Init( HMACContext * cx, const SECHashObject *hash_obj,
|
||||
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char hashed_secret[HASH_LENGTH_MAX];
|
||||
|
||||
/* required by FIPS 198 Section 3 */
|
||||
if (isFIPS && secret_len < hash_obj->length/2) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
cx->wasAllocated = PR_FALSE;
|
||||
cx->hashobj = hash_obj;
|
||||
cx->hash = cx->hashobj->create();
|
||||
if (cx->hash == NULL)
|
||||
goto loser;
|
||||
|
||||
if (secret_len > cx->hashobj->blocklength) {
|
||||
cx->hashobj->begin( cx->hash);
|
||||
cx->hashobj->update(cx->hash, secret, secret_len);
|
||||
PORT_Assert(cx->hashobj->length <= sizeof hashed_secret);
|
||||
cx->hashobj->end( cx->hash, hashed_secret, &secret_len,
|
||||
sizeof hashed_secret);
|
||||
if (secret_len != cx->hashobj->length) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
goto loser;
|
||||
}
|
||||
secret = (const unsigned char *)&hashed_secret[0];
|
||||
}
|
||||
|
||||
PORT_Memset(cx->ipad, 0x36, cx->hashobj->blocklength);
|
||||
PORT_Memset(cx->opad, 0x5c, cx->hashobj->blocklength);
|
||||
|
||||
/* fold secret into padding */
|
||||
for (i = 0; i < secret_len; i++) {
|
||||
cx->ipad[i] ^= secret[i];
|
||||
cx->opad[i] ^= secret[i];
|
||||
}
|
||||
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
|
||||
if (cx->hash != NULL)
|
||||
cx->hashobj->destroy(cx->hash, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
HMACContext *
|
||||
HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS)
|
||||
{
|
||||
SECStatus rv;
|
||||
HMACContext * cx = PORT_ZNew(HMACContext);
|
||||
if (cx == NULL)
|
||||
return NULL;
|
||||
rv = HMAC_Init(cx, hash_obj, secret, secret_len, isFIPS);
|
||||
cx->wasAllocated = PR_TRUE;
|
||||
if (rv != SECSuccess) {
|
||||
PORT_Free(cx); /* contains no secret info */
|
||||
cx = NULL;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
HMAC_Begin(HMACContext *cx)
|
||||
{
|
||||
/* start inner hash */
|
||||
cx->hashobj->begin(cx->hash);
|
||||
cx->hashobj->update(cx->hash, cx->ipad, cx->hashobj->blocklength);
|
||||
}
|
||||
|
||||
void
|
||||
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len)
|
||||
{
|
||||
cx->hashobj->update(cx->hash, data, data_len);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
|
||||
unsigned int max_result_len)
|
||||
{
|
||||
if (max_result_len < cx->hashobj->length) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->hashobj->end(cx->hash, result, result_len, max_result_len);
|
||||
if (*result_len != cx->hashobj->length)
|
||||
return SECFailure;
|
||||
|
||||
cx->hashobj->begin(cx->hash);
|
||||
cx->hashobj->update(cx->hash, cx->opad, cx->hashobj->blocklength);
|
||||
cx->hashobj->update(cx->hash, result, *result_len);
|
||||
cx->hashobj->end(cx->hash, result, result_len, max_result_len);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
HMACContext *
|
||||
HMAC_Clone(HMACContext *cx)
|
||||
{
|
||||
HMACContext *newcx;
|
||||
|
||||
newcx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
|
||||
if (newcx == NULL)
|
||||
goto loser;
|
||||
|
||||
newcx->wasAllocated = PR_TRUE;
|
||||
newcx->hashobj = cx->hashobj;
|
||||
newcx->hash = cx->hashobj->clone(cx->hash);
|
||||
if (newcx->hash == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(newcx->ipad, cx->ipad, cx->hashobj->blocklength);
|
||||
PORT_Memcpy(newcx->opad, cx->opad, cx->hashobj->blocklength);
|
||||
return newcx;
|
||||
|
||||
loser:
|
||||
HMAC_Destroy(newcx, PR_TRUE);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _ALGHMAC_H_
|
||||
#define _ALGHMAC_H_
|
||||
|
||||
typedef struct HMACContextStr HMACContext;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/* destroy HMAC context */
|
||||
extern void
|
||||
HMAC_Destroy(HMACContext *cx, PRBool freeit);
|
||||
|
||||
/* create HMAC context
|
||||
* hash_obj hash object from SECRawHashObjects[]
|
||||
* secret the secret with which the HMAC is performed.
|
||||
* secret_len the length of the secret.
|
||||
* isFIPS true if conforming to FIPS 198.
|
||||
*
|
||||
* NULL is returned if an error occurs.
|
||||
*/
|
||||
extern HMACContext *
|
||||
HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS);
|
||||
|
||||
/* like HMAC_Create, except caller allocates HMACContext. */
|
||||
SECStatus
|
||||
HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj,
|
||||
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS);
|
||||
|
||||
/* reset HMAC for a fresh round */
|
||||
extern void
|
||||
HMAC_Begin(HMACContext *cx);
|
||||
|
||||
/* update HMAC
|
||||
* cx HMAC Context
|
||||
* data the data to perform HMAC on
|
||||
* data_len the length of the data to process
|
||||
*/
|
||||
extern void
|
||||
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len);
|
||||
|
||||
/* Finish HMAC -- place the results within result
|
||||
* cx HMAC context
|
||||
* result buffer for resulting hmac'd data
|
||||
* result_len where the resultant hmac length is stored
|
||||
* max_result_len maximum possible length that can be stored in result
|
||||
*/
|
||||
extern SECStatus
|
||||
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
|
||||
unsigned int max_result_len);
|
||||
|
||||
/* clone a copy of the HMAC state. this is usefult when you would
|
||||
* need to keep a running hmac but also need to extract portions
|
||||
* partway through the process.
|
||||
*/
|
||||
extern HMACContext *
|
||||
HMAC_Clone(HMACContext *cx);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* arcfive.c - stubs for RC5 - NOT a working implementation!
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: arcfive.c,v 1.6 2008-11-18 19:48:21 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "blapi.h"
|
||||
#include "prerror.h"
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** RC5 symmetric block cypher -- 64-bit block size
|
||||
*/
|
||||
|
||||
/*
|
||||
** Create a new RC5 context suitable for RC5 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC5_CBC)
|
||||
** "mode" one of NSS_RC5 or NSS_RC5_CBC
|
||||
**
|
||||
** When mode is set to NSS_RC5_CBC the RC5 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC5Context *
|
||||
RC5_CreateContext(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC5 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC5_DestroyContext(RC5Context *cx, PRBool freeit)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 encryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the encrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Encrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 decryption.
|
||||
** "cx" the context
|
||||
** "output" the output buffer to store the decrypted data.
|
||||
** "outputLen" how much data is stored in "output". Set by the routine
|
||||
** after some data is stored in output.
|
||||
** "maxOutputLen" the maximum amount of data that can ever be
|
||||
** stored in "output"
|
||||
** "input" the input data
|
||||
** "inputLen" the amount of input data
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Decrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Marc Bevand <bevand_m@epita.fr> .
|
||||
# Portions created by the Initial Developer are
|
||||
# Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# ** ARCFOUR implementation optimized for AMD64.
|
||||
# **
|
||||
# ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
# ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.globl ARCFOUR
|
||||
.type ARCFOUR,@function
|
||||
ARCFOUR:
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
movq %rdi, %rbp # key = ARG(key)
|
||||
movq %rsi, %rbx # rbx = ARG(len)
|
||||
movq %rdx, %rsi # in = ARG(in)
|
||||
movq %rcx, %rdi # out = ARG(out)
|
||||
movq (%rbp), %rcx # x = key->x
|
||||
movq 8(%rbp), %rdx # y = key->y
|
||||
addq $16, %rbp # d = key->data
|
||||
incq %rcx # x++
|
||||
andq $255, %rcx # x &= 0xff
|
||||
leaq -8(%rbx,%rsi), %rbx # rbx = in+len-8
|
||||
movq %rbx, %r9 # tmp = in+len-8
|
||||
movq 0(%rbp,%rcx,8), %rax # tx = d[x]
|
||||
cmpq %rsi, %rbx # cmp in with in+len-8
|
||||
jl .Lend # jump if (in+len-8 < in)
|
||||
|
||||
.Lstart:
|
||||
addq $8, %rsi # increment in
|
||||
addq $8, %rdi # increment out
|
||||
|
||||
# generate the next 8 bytes of the rc4 stream into %r8
|
||||
movq $8, %r11 # byte counter
|
||||
1: addb %al, %dl # y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx # ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) # d[x] = ty
|
||||
addb %al, %bl # val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) # d[y] = tx
|
||||
incb %cl # x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax # tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b # val = d[val]
|
||||
decb %r11b
|
||||
rorq $8, %r8 # (ror does not change ZF)
|
||||
jnz 1b
|
||||
|
||||
# xor 8 bytes
|
||||
xorq -8(%rsi), %r8
|
||||
cmpq %r9, %rsi # cmp in+len-8 with in
|
||||
movq %r8, -8(%rdi)
|
||||
jle .Lstart # jump if (in <= in+len-8)
|
||||
|
||||
.Lend:
|
||||
addq $8, %r9 # tmp = in+len
|
||||
|
||||
# handle the last bytes, one by one
|
||||
1: cmpq %rsi, %r9 # cmp in with in+len
|
||||
jle .Lfinished # jump if (in+len <= in)
|
||||
addb %al, %dl # y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx # ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) # d[x] = ty
|
||||
addb %al, %bl # val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) # d[y] = tx
|
||||
incb %cl # x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax # tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b # val = d[val]
|
||||
xorb (%rsi), %r8b # xor 1 byte
|
||||
movb %r8b, (%rdi)
|
||||
incq %rsi # in++
|
||||
incq %rdi # out++
|
||||
jmp 1b
|
||||
|
||||
.Lfinished:
|
||||
decq %rcx # x--
|
||||
movb %dl, -8(%rbp) # key->y = y
|
||||
movb %cl, -16(%rbp) # key->x = x
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
ret
|
||||
.L_ARCFOUR_end:
|
||||
.size ARCFOUR,.L_ARCFOUR_end-ARCFOUR
|
||||
|
||||
# Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
.previous
|
||||
@@ -1,139 +0,0 @@
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; Marc Bevand <bevand_m@epita.fr> .
|
||||
; Portions created by the Initial Developer are
|
||||
; Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s): Makoto Kato (m_kato@ga2.so-net.ne.jp)
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
; ** ARCFOUR implementation optimized for AMD64.
|
||||
; **
|
||||
; ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
; ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.CODE
|
||||
|
||||
; extern void ARCFOUR(RC4Context *cx, unsigned long long inputLen,
|
||||
; const unsigned char *input, unsigned char *output);
|
||||
|
||||
|
||||
ARCFOUR PROC
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push rsi
|
||||
push rdi
|
||||
|
||||
mov rbp, rcx ; key = ARG(key)
|
||||
mov rbx, rdx ; rbx = ARG(len)
|
||||
mov rsi, r8 ; in = ARG(in)
|
||||
mov rdi, r9 ; out = ARG(out)
|
||||
mov rcx, [rbp] ; x = key->x
|
||||
mov rdx, [rbp+8] ; y = key->y
|
||||
add rbp, 16 ; d = key->data
|
||||
inc rcx ; x++
|
||||
and rcx, 0ffh ; x &= 0xff
|
||||
lea rbx, [rbx+rsi-8] ; rbx = in+len-8
|
||||
mov r9, rbx ; tmp = in+len-8
|
||||
mov rax, [rbp+rcx*8] ; tx = d[x]
|
||||
cmp rbx, rsi ; cmp in with in+len-8
|
||||
jl Lend ; jump if (in+len-8 < in)
|
||||
|
||||
Lstart:
|
||||
add rsi, 8 ; increment in
|
||||
add rdi, 8 ; increment out
|
||||
|
||||
;
|
||||
; generate the next 8 bytes of the rc4 stream into r8
|
||||
;
|
||||
|
||||
mov r11, 8 ; byte counter
|
||||
|
||||
@@:
|
||||
add dl, al ; y += tx
|
||||
mov ebx, [rbp+rdx*8] ; ty = d[y]
|
||||
mov [rbp+rcx*8], ebx ; d[x] = ty
|
||||
add bl, al ; val = ty + tx
|
||||
mov [rbp+rdx*8], eax ; d[y] = tx
|
||||
inc cl ; x++ (NEXT ROUND)
|
||||
mov eax, [rbp+rcx*8] ; tx = d[x] (NEXT ROUND)
|
||||
mov r8b, [rbp+rbx*8] ; val = d[val]
|
||||
dec r11b
|
||||
ror r8, 8 ; (ror does not change ZF)
|
||||
jnz @b
|
||||
|
||||
;
|
||||
; xor 8 bytes
|
||||
;
|
||||
|
||||
xor r8, [rsi-8]
|
||||
cmp rsi, r9 ; cmp in+len-8 with in
|
||||
mov [rdi-8], r8
|
||||
jle Lstart
|
||||
|
||||
Lend:
|
||||
add r9, 8 ; tmp = in+len
|
||||
|
||||
;
|
||||
; handle the last bytes, one by one
|
||||
;
|
||||
|
||||
@@:
|
||||
cmp r9, rsi ; cmp in with in+len
|
||||
jle Lfinished ; jump if (in+len <= in)
|
||||
add dl, al ; y += tx
|
||||
mov ebx, [rbp+rdx*8] ; ty = d[y]
|
||||
mov [rbp+rcx*8], ebx ; d[x] = ty
|
||||
add bl, al ; val = ty + tx
|
||||
mov [rbp+rdx*8], eax ; d[y] = tx
|
||||
inc cl ; x++ (NEXT ROUND)
|
||||
mov eax, [rbp+rcx*8] ; tx = d[x] (NEXT ROUND)
|
||||
mov r8b, [rbp+rbx*8] ; val = d[val]
|
||||
xor r8b, [rsi] ; xor 1 byte
|
||||
mov [rdi], r8b
|
||||
inc rsi ; in++
|
||||
inc rdi
|
||||
jmp @b
|
||||
|
||||
Lfinished:
|
||||
dec rcx ; x--
|
||||
mov [rbp-8], dl ; key->y = y
|
||||
mov [rbp-16], cl ; key->x = x
|
||||
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
ARCFOUR ENDP
|
||||
|
||||
END
|
||||
@@ -1,116 +0,0 @@
|
||||
/ ***** BEGIN LICENSE BLOCK *****
|
||||
/ Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public License Version
|
||||
/ 1.1 (the "License"); you may not use this file except in compliance with
|
||||
/ the License. You may obtain a copy of the License at
|
||||
/ http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS IS" basis,
|
||||
/ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
/ for the specific language governing rights and limitations under the
|
||||
/ License.
|
||||
/
|
||||
/ The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
/
|
||||
/ The Initial Developer of the Original Code is
|
||||
/ Marc Bevand <bevand_m@epita.fr> .
|
||||
/ Portions created by the Initial Developer are
|
||||
/ Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the terms of
|
||||
/ either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
/ the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
/ in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
/ of those above. If you wish to allow use of your version of this file only
|
||||
/ under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
/ use your version of this file under the terms of the MPL, indicate your
|
||||
/ decision by deleting the provisions above and replace them with the notice
|
||||
/ and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
/ the provisions above, a recipient may use your version of this file under
|
||||
/ the terms of any one of the MPL, the GPL or the LGPL.
|
||||
/
|
||||
/ ***** END LICENSE BLOCK *****
|
||||
|
||||
/ ** ARCFOUR implementation optimized for AMD64.
|
||||
/ **
|
||||
/ ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
/ ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.globl ARCFOUR
|
||||
.type ARCFOUR,@function
|
||||
ARCFOUR:
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
movq %rdi, %rbp / key = ARG(key)
|
||||
movq %rsi, %rbx / rbx = ARG(len)
|
||||
movq %rdx, %rsi / in = ARG(in)
|
||||
movq %rcx, %rdi / out = ARG(out)
|
||||
movq (%rbp), %rcx / x = key->x
|
||||
movq 8(%rbp), %rdx / y = key->y
|
||||
addq $16, %rbp / d = key->data
|
||||
incq %rcx / x++
|
||||
andq $255, %rcx / x &= 0xff
|
||||
leaq -8(%rbx,%rsi), %rbx / rbx = in+len-8
|
||||
movq %rbx, %r9 / tmp = in+len-8
|
||||
movq 0(%rbp,%rcx,8), %rax / tx = d[x]
|
||||
cmpq %rsi, %rbx / cmp in with in+len-8
|
||||
jl .Lend / jump if (in+len-8 < in)
|
||||
|
||||
.Lstart:
|
||||
addq $8, %rsi / increment in
|
||||
addq $8, %rdi / increment out
|
||||
|
||||
/ generate the next 8 bytes of the rc4 stream into %r8
|
||||
movq $8, %r11 / byte counter
|
||||
1: addb %al, %dl / y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx / ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) / d[x] = ty
|
||||
addb %al, %bl / val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) / d[y] = tx
|
||||
incb %cl / x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax / tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b / val = d[val]
|
||||
decb %r11b
|
||||
rorq $8, %r8 / (ror does not change ZF)
|
||||
jnz 1b
|
||||
|
||||
/ xor 8 bytes
|
||||
xorq -8(%rsi), %r8
|
||||
cmpq %r9, %rsi / cmp in+len-8 with in
|
||||
movq %r8, -8(%rdi)
|
||||
jle .Lstart / jump if (in <= in+len-8)
|
||||
|
||||
.Lend:
|
||||
addq $8, %r9 / tmp = in+len
|
||||
|
||||
/ handle the last bytes, one by one
|
||||
1: cmpq %rsi, %r9 / cmp in with in+len
|
||||
jle .Lfinished / jump if (in+len <= in)
|
||||
addb %al, %dl / y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx / ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) / d[x] = ty
|
||||
addb %al, %bl / val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) / d[y] = tx
|
||||
incb %cl / x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax / tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b / val = d[val]
|
||||
xorb (%rsi), %r8b / xor 1 byte
|
||||
movb %r8b, (%rdi)
|
||||
incq %rsi / in++
|
||||
incq %rdi / out++
|
||||
jmp 1b
|
||||
|
||||
.Lfinished:
|
||||
decq %rcx / x--
|
||||
movb %dl, -8(%rbp) / key->y = y
|
||||
movb %cl, -16(%rbp) / key->x = x
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
ret
|
||||
.L_ARCFOUR_end:
|
||||
.size ARCFOUR,.L_ARCFOUR_end-ARCFOUR
|
||||
@@ -1,646 +0,0 @@
|
||||
/* arcfour.c - the arc four algorithm.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* See NOTES ON UMRs, Unititialized Memory Reads, below. */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "blapi.h"
|
||||
|
||||
/* Architecture-dependent defines */
|
||||
|
||||
#if defined(SOLARIS) || defined(HPUX) || defined(i386) || defined(IRIX) || \
|
||||
defined(_WIN64)
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
#define CONVERT_TO_WORDS
|
||||
#endif
|
||||
|
||||
#if defined(AIX) || defined(OSF1) || defined(NSS_BEVAND_ARCFOUR)
|
||||
/* Treat array variables as words, not bytes, on CPUs that take
|
||||
* much longer to write bytes than to write words, or when using
|
||||
* assembler code that required it.
|
||||
*/
|
||||
#define USE_WORD
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#undef WORD
|
||||
#define WORD ARC4WORD
|
||||
#endif
|
||||
|
||||
#if (defined(IS_64))
|
||||
typedef PRUint64 WORD;
|
||||
#else
|
||||
typedef PRUint32 WORD;
|
||||
#endif
|
||||
#define WORDSIZE sizeof(WORD)
|
||||
|
||||
#if defined(USE_WORD)
|
||||
typedef WORD Stype;
|
||||
#else
|
||||
typedef PRUint8 Stype;
|
||||
#endif
|
||||
|
||||
#define ARCFOUR_STATE_SIZE 256
|
||||
|
||||
#define MASK1BYTE (WORD)(0xff)
|
||||
|
||||
#define SWAP(a, b) \
|
||||
tmp = a; \
|
||||
a = b; \
|
||||
b = tmp;
|
||||
|
||||
/*
|
||||
* State information for stream cipher.
|
||||
*/
|
||||
struct RC4ContextStr
|
||||
{
|
||||
#if defined(NSS_ARCFOUR_IJ_B4_S) || defined(NSS_BEVAND_ARCFOUR)
|
||||
Stype i;
|
||||
Stype j;
|
||||
Stype S[ARCFOUR_STATE_SIZE];
|
||||
#else
|
||||
Stype S[ARCFOUR_STATE_SIZE];
|
||||
Stype i;
|
||||
Stype j;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* array indices [0..255] to initialize cx->S array (faster than loop).
|
||||
*/
|
||||
static const Stype Kinit[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
RC4Context *
|
||||
RC4_AllocateContext(void)
|
||||
{
|
||||
return PORT_ZNew(RC4Context);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len,
|
||||
const unsigned char * unused1, int unused2,
|
||||
unsigned int unused3, unsigned int unused4)
|
||||
{
|
||||
int i;
|
||||
PRUint8 j, tmp;
|
||||
PRUint8 K[256];
|
||||
PRUint8 *L;
|
||||
|
||||
/* verify the key length. */
|
||||
PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
|
||||
if (len < 0 || len >= ARCFOUR_STATE_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize the state using array indices. */
|
||||
memcpy(cx->S, Kinit, sizeof cx->S);
|
||||
/* Fill in K repeatedly with values from key. */
|
||||
L = K;
|
||||
for (i = sizeof K; i > len; i-= len) {
|
||||
memcpy(L, key, len);
|
||||
L += len;
|
||||
}
|
||||
memcpy(L, key, i);
|
||||
/* Stir the state of the generator. At this point it is assumed
|
||||
* that the key is the size of the state buffer. If this is not
|
||||
* the case, the key bytes are repeated to fill the buffer.
|
||||
*/
|
||||
j = 0;
|
||||
#define ARCFOUR_STATE_STIR(ii) \
|
||||
j = j + cx->S[ii] + K[ii]; \
|
||||
SWAP(cx->S[ii], cx->S[j]);
|
||||
for (i=0; i<ARCFOUR_STATE_SIZE; i++) {
|
||||
ARCFOUR_STATE_STIR(i);
|
||||
}
|
||||
cx->i = 0;
|
||||
cx->j = 0;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a new generator.
|
||||
*/
|
||||
RC4Context *
|
||||
RC4_CreateContext(const unsigned char *key, int len)
|
||||
{
|
||||
RC4Context *cx = RC4_AllocateContext();
|
||||
if (cx) {
|
||||
SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
cx = NULL;
|
||||
}
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
|
||||
{
|
||||
if (freeit)
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
}
|
||||
|
||||
#if defined(NSS_BEVAND_ARCFOUR)
|
||||
extern void ARCFOUR(RC4Context *cx, WORD inputLen,
|
||||
const unsigned char *input, unsigned char *output);
|
||||
#else
|
||||
/*
|
||||
* Generate the next byte in the stream.
|
||||
*/
|
||||
#define ARCFOUR_NEXT_BYTE() \
|
||||
tmpSi = cx->S[++tmpi]; \
|
||||
tmpj += tmpSi; \
|
||||
tmpSj = cx->S[tmpj]; \
|
||||
cx->S[tmpi] = tmpSj; \
|
||||
cx->S[tmpj] = tmpSi; \
|
||||
t = tmpSi + tmpSj;
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Straight ARCFOUR op. No optimization.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_no_opt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index=0; index < inputLen; index++) {
|
||||
/* Generate next byte from stream. */
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
/* output = next stream byte XOR next input byte */
|
||||
output[index] = cx->S[t] ^ input[index];
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
#else
|
||||
/* !CONVERT_TO_WORDS */
|
||||
|
||||
/*
|
||||
* Byte-at-a-time ARCFOUR, unrolling the loop into 8 pieces.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_unrolled(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[0] = cx->S[t] ^ input[0];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[1] = cx->S[t] ^ input[1];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[2] = cx->S[t] ^ input[2];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[3] = cx->S[t] ^ input[3];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[4] = cx->S[t] ^ input[4];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[5] = cx->S[t] ^ input[5];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[6] = cx->S[t] ^ input[6];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[7] = cx->S[t] ^ input[7];
|
||||
}
|
||||
index = inputLen % 8;
|
||||
if (index) {
|
||||
input += index;
|
||||
output += index;
|
||||
switch (index) {
|
||||
case 7:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
|
||||
case 6:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
|
||||
case 5:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
|
||||
case 4:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
|
||||
case 3:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
|
||||
case 2:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
|
||||
case 1:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
|
||||
default:
|
||||
/* FALLTHRU */
|
||||
; /* hp-ux build breaks without this */
|
||||
}
|
||||
}
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT4BYTES_L(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n ); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);
|
||||
#else
|
||||
#define ARCFOUR_NEXT4BYTES_B(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n );
|
||||
#endif
|
||||
|
||||
#if (defined(IS_64) && !defined(__sparc)) || defined(NSS_USE_64)
|
||||
/* 64-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#else
|
||||
/* 32-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define RSH <<
|
||||
#define LSH >>
|
||||
#else
|
||||
#define RSH >>
|
||||
#define LSH <<
|
||||
#endif
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/* NOTE about UMRs, Uninitialized Memory Reads.
|
||||
*
|
||||
* This code reads all input data a WORD at a time, rather than byte at
|
||||
* a time, and writes all output data a WORD at a time. Shifting and
|
||||
* masking is used to remove unwanted data and realign bytes when
|
||||
* needed. The first and last words of output are read, modified, and
|
||||
* written when needed to preserve any unchanged bytes. This is a huge
|
||||
* win on machines with high memory latency.
|
||||
*
|
||||
* However, when the input and output buffers do not begin and end on WORD
|
||||
* boundaries, and the WORDS in memory that contain the first and last
|
||||
* bytes of those buffers contain uninitialized data, then this code will
|
||||
* read those uninitialized bytes, causing a UMR error to be reported by
|
||||
* some tools.
|
||||
*
|
||||
* These UMRs are NOT a problem, NOT errors, and do NOT need to be "fixed".
|
||||
*
|
||||
* All the words read and written contain at least one byte that is
|
||||
* part of the input data or output data. No words are read or written
|
||||
* that do not contain data that is part of the buffer. Therefore,
|
||||
* these UMRs cannot cause page faults or other problems unless the
|
||||
* buffers have been assigned to improper addresses that would cause
|
||||
* page faults with or without UMRs.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_wordconv(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE;
|
||||
ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE;
|
||||
register WORD streamWord, mask;
|
||||
register WORD *pInWord, *pOutWord;
|
||||
register WORD inWord, nextInWord;
|
||||
PRUint8 t;
|
||||
register Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int byteCount;
|
||||
unsigned int bufShift, invBufShift;
|
||||
int i;
|
||||
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (inputLen < 2*WORDSIZE) {
|
||||
/* Ignore word conversion, do byte-at-a-time */
|
||||
return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
pInWord = (WORD *)(input - inOffset);
|
||||
if (inOffset < outOffset) {
|
||||
bufShift = 8*(outOffset - inOffset);
|
||||
invBufShift = 8*WORDSIZE - bufShift;
|
||||
} else {
|
||||
invBufShift = 8*(inOffset - outOffset);
|
||||
bufShift = 8*WORDSIZE - invBufShift;
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 1: */
|
||||
/* If the first output word is partial, consume the bytes in the */
|
||||
/* first partial output word by loading one or two words of */
|
||||
/* input and shifting them accordingly. Otherwise, just load */
|
||||
/* in the first word of input. At the end of this block, at */
|
||||
/* least one partial word of input should ALWAYS be loaded. */
|
||||
/*****************************************************************/
|
||||
if (outOffset) {
|
||||
/* Generate input and stream words aligned relative to the
|
||||
* partial output buffer.
|
||||
*/
|
||||
byteCount = WORDSIZE - outOffset;
|
||||
pOutWord = (WORD *)(output - outOffset);
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) {
|
||||
#else
|
||||
for (i = byteCount - 1; i >= 0; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
inWord = *pInWord++; /* UMR? see comments above. */
|
||||
/* If buffers are relatively misaligned, shift the bytes in inWord
|
||||
* to be aligned to the output buffer.
|
||||
*/
|
||||
nextInWord = 0;
|
||||
if (inOffset < outOffset) {
|
||||
/* Have more bytes than needed, shift remainder into nextInWord */
|
||||
nextInWord = inWord LSH 8*(inOffset + byteCount);
|
||||
inWord = inWord RSH bufShift;
|
||||
} else if (inOffset > outOffset) {
|
||||
/* Didn't get enough bytes from current input word, load another
|
||||
* word and then shift remainder into nextInWord.
|
||||
*/
|
||||
nextInWord = *pInWord++;
|
||||
inWord = (inWord LSH invBufShift) |
|
||||
(nextInWord RSH bufShift);
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
}
|
||||
/* Store output of first partial word */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
/* UMR? See comments above. */
|
||||
|
||||
/* Consumed byteCount bytes of input */
|
||||
inputLen -= byteCount;
|
||||
/* move to next word of output */
|
||||
pOutWord++;
|
||||
/* inWord has been consumed, but there may be bytes in nextInWord */
|
||||
inWord = nextInWord;
|
||||
} else {
|
||||
/* output is word-aligned */
|
||||
pOutWord = (WORD *)output;
|
||||
if (inOffset) {
|
||||
/* Input is not word-aligned. The first word load of input
|
||||
* will not produce a full word of input bytes, so one word
|
||||
* must be pre-loaded. The main loop below will load in the
|
||||
* next input word and shift some of its bytes into inWord
|
||||
* in order to create a full input word. Note that the main
|
||||
* loop must execute at least once because the input must
|
||||
* be at least two words.
|
||||
*/
|
||||
inWord = *pInWord++; /* UMR? see comments above. */
|
||||
inWord = inWord LSH invBufShift;
|
||||
} else {
|
||||
/* Input is word-aligned. The first word load of input
|
||||
* will produce a full word of input bytes, so nothing
|
||||
* needs to be loaded here.
|
||||
*/
|
||||
inWord = 0;
|
||||
}
|
||||
}
|
||||
/* Output buffer is aligned, inOffset is now measured relative to
|
||||
* outOffset (and not a word boundary).
|
||||
*/
|
||||
inOffset = (inOffset + WORDSIZE - outOffset) % WORDSIZE;
|
||||
/*****************************************************************/
|
||||
/* Step 2: main loop */
|
||||
/* At this point the output buffer is word-aligned. Any unused */
|
||||
/* bytes from above will be in inWord (shifted correctly). If */
|
||||
/* the input buffer is unaligned relative to the output buffer, */
|
||||
/* shifting has to be done. */
|
||||
/*****************************************************************/
|
||||
if (inOffset) {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
nextInWord = *pInWord++;
|
||||
inWord |= nextInWord RSH bufShift;
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
inWord = nextInWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
/* If the amount of remaining input is greater than the amount
|
||||
* bytes pulled from the current input word, need to do another
|
||||
* word load. What's left in inWord will be consumed in step 3.
|
||||
*/
|
||||
if (inputLen > WORDSIZE - inOffset)
|
||||
inWord |= *pInWord RSH bufShift; /* UMR? See above. */
|
||||
} else {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
inWord = *pInWord++;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
} else {
|
||||
/* A partial input word remains at the tail. Load it.
|
||||
* The relevant bytes will be consumed in step 3.
|
||||
*/
|
||||
inWord = *pInWord; /* UMR? See comments above */
|
||||
}
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 3: */
|
||||
/* A partial word of input remains, and it is already loaded */
|
||||
/* into nextInWord. Shift appropriately and consume the bytes */
|
||||
/* used in the partial word. */
|
||||
/*****************************************************************/
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = 0; i < inputLen; ++i) {
|
||||
#else
|
||||
for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
/* UMR? See comments above. */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
#endif /* NSS_BEVAND_ARCFOUR */
|
||||
|
||||
SECStatus
|
||||
RC4_Encrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
#if defined(NSS_BEVAND_ARCFOUR)
|
||||
ARCFOUR(cx, inputLen, input, output);
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
#elif defined( CONVERT_TO_WORDS )
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* decrypt and encrypt are same operation. */
|
||||
#if defined(NSS_BEVAND_ARCFOUR)
|
||||
ARCFOUR(cx, inputLen, input, output);
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
#elif defined( CONVERT_TO_WORDS )
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef CONVERT_TO_WORDS
|
||||
#undef USE_WORD
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* blapii.h - private data structures and prototypes for the crypto library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Network Security Services Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _BLAPII_H_
|
||||
#define _BLAPII_H_
|
||||
|
||||
#include "blapit.h"
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
#if defined(XP_UNIX) && !defined(NO_CHECK_FORK)
|
||||
|
||||
extern PRBool bl_parentForkedAfterC_Initialize;
|
||||
|
||||
#define SKIP_AFTER_FORK(x) if (!bl_parentForkedAfterC_Initialize) x
|
||||
|
||||
#else
|
||||
|
||||
#define SKIP_AFTER_FORK(x) x
|
||||
|
||||
#endif
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _BLAPII_H_ */
|
||||
|
||||
@@ -1,389 +0,0 @@
|
||||
/*
|
||||
* blapit.h - public data structures for the crypto library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: blapit.h,v 1.22 2008-12-17 06:09:12 nelson%bolyard.com Exp $ */
|
||||
|
||||
#ifndef _BLAPIT_H_
|
||||
#define _BLAPIT_H_
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "prlink.h"
|
||||
#include "plarena.h"
|
||||
#include "ecl-exp.h"
|
||||
|
||||
|
||||
/* RC2 operation modes */
|
||||
#define NSS_RC2 0
|
||||
#define NSS_RC2_CBC 1
|
||||
|
||||
/* RC5 operation modes */
|
||||
#define NSS_RC5 0
|
||||
#define NSS_RC5_CBC 1
|
||||
|
||||
/* DES operation modes */
|
||||
#define NSS_DES 0
|
||||
#define NSS_DES_CBC 1
|
||||
#define NSS_DES_EDE3 2
|
||||
#define NSS_DES_EDE3_CBC 3
|
||||
|
||||
#define DES_KEY_LENGTH 8 /* Bytes */
|
||||
|
||||
/* AES operation modes */
|
||||
#define NSS_AES 0
|
||||
#define NSS_AES_CBC 1
|
||||
|
||||
/* Camellia operation modes */
|
||||
#define NSS_CAMELLIA 0
|
||||
#define NSS_CAMELLIA_CBC 1
|
||||
|
||||
/* SEED operation modes */
|
||||
#define NSS_SEED 0
|
||||
#define NSS_SEED_CBC 1
|
||||
|
||||
#define DSA_SIGNATURE_LEN 40 /* Bytes */
|
||||
#define DSA_SUBPRIME_LEN 20 /* Bytes */
|
||||
|
||||
/* XXX We shouldn't have to hard code this limit. For
|
||||
* now, this is the quickest way to support ECDSA signature
|
||||
* processing (ECDSA signature lengths depend on curve
|
||||
* size). This limit is sufficient for curves upto
|
||||
* 576 bits.
|
||||
*/
|
||||
#define MAX_ECKEY_LEN 72 /* Bytes */
|
||||
|
||||
/*
|
||||
* Number of bytes each hash algorithm produces
|
||||
*/
|
||||
#define MD2_LENGTH 16 /* Bytes */
|
||||
#define MD5_LENGTH 16 /* Bytes */
|
||||
#define SHA1_LENGTH 20 /* Bytes */
|
||||
#define SHA256_LENGTH 32 /* bytes */
|
||||
#define SHA384_LENGTH 48 /* bytes */
|
||||
#define SHA512_LENGTH 64 /* bytes */
|
||||
#define HASH_LENGTH_MAX SHA512_LENGTH
|
||||
|
||||
/*
|
||||
* Input block size for each hash algorithm.
|
||||
*/
|
||||
|
||||
#define MD2_BLOCK_LENGTH 64 /* bytes */
|
||||
#define MD5_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA1_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA256_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA384_BLOCK_LENGTH 128 /* bytes */
|
||||
#define SHA512_BLOCK_LENGTH 128 /* bytes */
|
||||
#define HASH_BLOCK_LENGTH_MAX SHA512_BLOCK_LENGTH
|
||||
|
||||
#define AES_KEY_WRAP_IV_BYTES 8
|
||||
#define AES_KEY_WRAP_BLOCK_SIZE 8 /* bytes */
|
||||
#define AES_BLOCK_SIZE 16 /* bytes */
|
||||
|
||||
#define CAMELLIA_BLOCK_SIZE 16 /* bytes */
|
||||
|
||||
#define SEED_BLOCK_SIZE 16 /* bytes */
|
||||
#define SEED_KEY_LENGTH 16 /* bytes */
|
||||
|
||||
#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
/*
|
||||
* These values come from the initial key size limits from the PKCS #11
|
||||
* module. They may be arbitrarily adjusted to any value freebl supports.
|
||||
*/
|
||||
#define RSA_MIN_MODULUS_BITS 128
|
||||
#define RSA_MAX_MODULUS_BITS 8192
|
||||
#define RSA_MAX_EXPONENT_BITS 64
|
||||
#define DH_MIN_P_BITS 128
|
||||
#define DH_MAX_P_BITS 2236
|
||||
|
||||
/*
|
||||
* The FIPS 186 algorithm for generating primes P and Q allows only 9
|
||||
* distinct values for the length of P, and only one value for the
|
||||
* length of Q.
|
||||
* The algorithm uses a variable j to indicate which of the 9 lengths
|
||||
* of P is to be used.
|
||||
* The following table relates j to the lengths of P and Q in bits.
|
||||
*
|
||||
* j bits in P bits in Q
|
||||
* _ _________ _________
|
||||
* 0 512 160
|
||||
* 1 576 160
|
||||
* 2 640 160
|
||||
* 3 704 160
|
||||
* 4 768 160
|
||||
* 5 832 160
|
||||
* 6 896 160
|
||||
* 7 960 160
|
||||
* 8 1024 160
|
||||
*
|
||||
* The FIPS-186 compliant PQG generator takes j as an input parameter.
|
||||
*/
|
||||
|
||||
#define DSA_Q_BITS 160
|
||||
#define DSA_MAX_P_BITS 1024
|
||||
#define DSA_MIN_P_BITS 512
|
||||
|
||||
/*
|
||||
* function takes desired number of bits in P,
|
||||
* returns index (0..8) or -1 if number of bits is invalid.
|
||||
*/
|
||||
#define PQG_PBITS_TO_INDEX(bits) \
|
||||
(((bits) < 512 || (bits) > 1024 || (bits) % 64) ? \
|
||||
-1 : (int)((bits)-512)/64)
|
||||
|
||||
/*
|
||||
* function takes index (0-8)
|
||||
* returns number of bits in P for that index, or -1 if index is invalid.
|
||||
*/
|
||||
#define PQG_INDEX_TO_PBITS(j) (((unsigned)(j) > 8) ? -1 : (512 + 64 * (j)))
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Opaque objects
|
||||
*/
|
||||
|
||||
struct DESContextStr ;
|
||||
struct RC2ContextStr ;
|
||||
struct RC4ContextStr ;
|
||||
struct RC5ContextStr ;
|
||||
struct AESContextStr ;
|
||||
struct CamelliaContextStr ;
|
||||
struct MD2ContextStr ;
|
||||
struct MD5ContextStr ;
|
||||
struct SHA1ContextStr ;
|
||||
struct SHA256ContextStr ;
|
||||
struct SHA512ContextStr ;
|
||||
struct AESKeyWrapContextStr ;
|
||||
struct SEEDContextStr ;
|
||||
|
||||
typedef struct DESContextStr DESContext;
|
||||
typedef struct RC2ContextStr RC2Context;
|
||||
typedef struct RC4ContextStr RC4Context;
|
||||
typedef struct RC5ContextStr RC5Context;
|
||||
typedef struct AESContextStr AESContext;
|
||||
typedef struct CamelliaContextStr CamelliaContext;
|
||||
typedef struct MD2ContextStr MD2Context;
|
||||
typedef struct MD5ContextStr MD5Context;
|
||||
typedef struct SHA1ContextStr SHA1Context;
|
||||
typedef struct SHA256ContextStr SHA256Context;
|
||||
typedef struct SHA512ContextStr SHA512Context;
|
||||
/* SHA384Context is really a SHA512ContextStr. This is not a mistake. */
|
||||
typedef struct SHA512ContextStr SHA384Context;
|
||||
typedef struct AESKeyWrapContextStr AESKeyWrapContext;
|
||||
typedef struct SEEDContextStr SEEDContext;
|
||||
|
||||
/***************************************************************************
|
||||
** RSA Public and Private Key structures
|
||||
*/
|
||||
|
||||
/* member names from PKCS#1, section 7.1 */
|
||||
struct RSAPublicKeyStr {
|
||||
PLArenaPool * arena;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
};
|
||||
typedef struct RSAPublicKeyStr RSAPublicKey;
|
||||
|
||||
/* member names from PKCS#1, section 7.2 */
|
||||
struct RSAPrivateKeyStr {
|
||||
PLArenaPool * arena;
|
||||
SECItem version;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
SECItem privateExponent;
|
||||
SECItem prime1;
|
||||
SECItem prime2;
|
||||
SECItem exponent1;
|
||||
SECItem exponent2;
|
||||
SECItem coefficient;
|
||||
};
|
||||
typedef struct RSAPrivateKeyStr RSAPrivateKey;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** DSA Public and Private Key and related structures
|
||||
*/
|
||||
|
||||
struct PQGParamsStr {
|
||||
PLArenaPool *arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem subPrime; /* q */
|
||||
SECItem base; /* g */
|
||||
/* XXX chrisk: this needs to be expanded to hold j and validationParms (RFC2459 7.3.2) */
|
||||
};
|
||||
typedef struct PQGParamsStr PQGParams;
|
||||
|
||||
struct PQGVerifyStr {
|
||||
PLArenaPool * arena; /* includes this struct, seed, & h. */
|
||||
unsigned int counter;
|
||||
SECItem seed;
|
||||
SECItem h;
|
||||
};
|
||||
typedef struct PQGVerifyStr PQGVerify;
|
||||
|
||||
struct DSAPublicKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DSAPublicKeyStr DSAPublicKey;
|
||||
|
||||
struct DSAPrivateKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DSAPrivateKeyStr DSAPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Diffie-Hellman Public and Private Key and related structures
|
||||
** Structure member names suggested by PKCS#3.
|
||||
*/
|
||||
|
||||
struct DHParamsStr {
|
||||
PLArenaPool * arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem base; /* g */
|
||||
};
|
||||
typedef struct DHParamsStr DHParams;
|
||||
|
||||
struct DHPublicKeyStr {
|
||||
PLArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DHPublicKeyStr DHPublicKey;
|
||||
|
||||
struct DHPrivateKeyStr {
|
||||
PLArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DHPrivateKeyStr DHPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Data structures used for elliptic curve parameters and
|
||||
** public and private keys.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The ECParams data structures can encode elliptic curve
|
||||
** parameters for both GFp and GF2m curves.
|
||||
*/
|
||||
|
||||
typedef enum { ec_params_explicit,
|
||||
ec_params_named
|
||||
} ECParamsType;
|
||||
|
||||
typedef enum { ec_field_GFp = 1,
|
||||
ec_field_GF2m
|
||||
} ECFieldType;
|
||||
|
||||
struct ECFieldIDStr {
|
||||
int size; /* field size in bits */
|
||||
ECFieldType type;
|
||||
union {
|
||||
SECItem prime; /* prime p for (GFp) */
|
||||
SECItem poly; /* irreducible binary polynomial for (GF2m) */
|
||||
} u;
|
||||
int k1; /* first coefficient of pentanomial or
|
||||
* the only coefficient of trinomial
|
||||
*/
|
||||
int k2; /* two remaining coefficients of pentanomial */
|
||||
int k3;
|
||||
};
|
||||
typedef struct ECFieldIDStr ECFieldID;
|
||||
|
||||
struct ECCurveStr {
|
||||
SECItem a; /* contains octet stream encoding of
|
||||
* field element (X9.62 section 4.3.3)
|
||||
*/
|
||||
SECItem b;
|
||||
SECItem seed;
|
||||
};
|
||||
typedef struct ECCurveStr ECCurve;
|
||||
|
||||
struct ECParamsStr {
|
||||
PLArenaPool * arena;
|
||||
ECParamsType type;
|
||||
ECFieldID fieldID;
|
||||
ECCurve curve;
|
||||
SECItem base;
|
||||
SECItem order;
|
||||
int cofactor;
|
||||
SECItem DEREncoding;
|
||||
ECCurveName name;
|
||||
SECItem curveOID;
|
||||
};
|
||||
typedef struct ECParamsStr ECParams;
|
||||
|
||||
struct ECPublicKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* elliptic curve point encoded as
|
||||
* octet stream.
|
||||
*/
|
||||
};
|
||||
typedef struct ECPublicKeyStr ECPublicKey;
|
||||
|
||||
struct ECPrivateKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* encoded ec point */
|
||||
SECItem privateValue; /* private big integer */
|
||||
SECItem version; /* As per SEC 1, Appendix C, Section C.4 */
|
||||
};
|
||||
typedef struct ECPrivateKeyStr ECPrivateKey;
|
||||
|
||||
typedef void * (*BLapiAllocateFunc)(void);
|
||||
typedef void (*BLapiDestroyContextFunc)(void *cx, PRBool freeit);
|
||||
typedef SECStatus (*BLapiInitContextFunc)(void *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *,
|
||||
int,
|
||||
unsigned int ,
|
||||
unsigned int );
|
||||
typedef SECStatus (*BLapiEncrypt)(void *cx, unsigned char *output,
|
||||
unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
#endif /* _BLAPIT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,79 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Camellia code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* NTT(Nippon Telegraph and Telephone Corporation).
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* $Id: camellia.h,v 1.1 2007-02-28 19:47:37 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _CAMELLIA_H_
|
||||
#define _CAMELLIA_H_ 1
|
||||
|
||||
#define CAMELLIA_BLOCK_SIZE 16 /* bytes */
|
||||
#define CAMELLIA_MIN_KEYSIZE 16 /* bytes */
|
||||
#define CAMELLIA_MAX_KEYSIZE 32 /* bytes */
|
||||
|
||||
#define CAMELLIA_MAX_EXPANDEDKEY (34*2) /* 32bit unit */
|
||||
|
||||
typedef PRUint32 KEY_TABLE_TYPE[CAMELLIA_MAX_EXPANDEDKEY];
|
||||
|
||||
typedef SECStatus CamelliaFunc(CamelliaContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
typedef SECStatus CamelliaBlockFunc(const PRUint32 *subkey,
|
||||
unsigned char *output,
|
||||
const unsigned char *input);
|
||||
|
||||
/* CamelliaContextStr
|
||||
*
|
||||
* Values which maintain the state for Camellia encryption/decryption.
|
||||
*
|
||||
* keysize - the number of key bits
|
||||
* worker - the encryption/decryption function to use with this context
|
||||
* iv - initialization vector for CBC mode
|
||||
* expandedKey - the round keys in 4-byte words
|
||||
*/
|
||||
struct CamelliaContextStr
|
||||
{
|
||||
PRUint32 keysize; /* bytes */
|
||||
CamelliaFunc *worker;
|
||||
PRUint32 expandedKey[CAMELLIA_MAX_EXPANDEDKEY];
|
||||
PRUint8 iv[CAMELLIA_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* _CAMELLIA_H_ */
|
||||
@@ -1,139 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# only do this in the outermost freebl build.
|
||||
ifndef FREEBL_CHILD_BUILD
|
||||
|
||||
# We're going to change this build so that it builds libfreebl.a with
|
||||
# just loader.c. Then we have to build this directory twice again to
|
||||
# build the two DSOs.
|
||||
# To build libfreebl.a with just loader.c, we must now override many
|
||||
# of the make variables setup by the prior inclusion of CORECONF's config.mk
|
||||
|
||||
CSRCS = loader.c
|
||||
SIMPLE_OBJS = $(CSRCS:.c=$(OBJ_SUFFIX))
|
||||
OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(SIMPLE_OBJS))
|
||||
ALL_TRASH := $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) so_locations
|
||||
|
||||
# this is not a recursive child make. We make a static lib. (archive)
|
||||
|
||||
# Override the values defined in coreconf's ruleset.mk.
|
||||
#
|
||||
# - (1) LIBRARY: a static (archival) library
|
||||
# - (2) SHARED_LIBRARY: a shared (dynamic link) library
|
||||
# - (3) IMPORT_LIBRARY: an import library, used only on Windows
|
||||
# - (4) PROGRAM: an executable binary
|
||||
#
|
||||
# override these variables to prevent building a DSO/DLL.
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
else
|
||||
|
||||
ifeq ($(FREEBL_NO_DEPEND),1)
|
||||
LOWHASH_SRCS = stubs.c nsslowhash.c
|
||||
LOWHASH_EXPORTS = nsslowhash.h
|
||||
MAPFILE_SOURCE = freebl_hash.def
|
||||
else
|
||||
MAPFILE_SOURCE = freebl.def
|
||||
endif
|
||||
|
||||
# This is a recursive child make. We build the shared lib.
|
||||
|
||||
TARGETS = $(SHARED_LIBRARY)
|
||||
LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
ifeq ($(OS_TARGET), SunOS)
|
||||
OS_LIBS += -lkstat
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
|
||||
# don't want the 32 in the shared library name
|
||||
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
|
||||
|
||||
RES = $(OBJDIR)/$(LIBRARY_NAME).res
|
||||
RESNAME = freebl.rc
|
||||
|
||||
ifndef WINCE
|
||||
ifdef NS_USE_GCC
|
||||
OS_LIBS += -lshell32
|
||||
else
|
||||
OS_LIBS += shell32.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib \
|
||||
-L$(NSSUTIL_LIB_DIR) \
|
||||
-lnssutil3 \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
else # ! NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
$(DIST)/lib/nssutil3.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
|
||||
$(NULL)
|
||||
endif # NS_USE_GCC
|
||||
|
||||
else
|
||||
|
||||
ifeq ($(FREEBL_NO_DEPEND),1)
|
||||
#drop pthreads as well
|
||||
OS_PTHREAD=
|
||||
else
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib \
|
||||
-L$(NSSUTIL_LIB_DIR) \
|
||||
-lnssutil3 \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH), Darwin)
|
||||
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
|
||||
endif
|
||||
|
||||
endif
|
||||
@@ -1,699 +0,0 @@
|
||||
/*
|
||||
* des.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Make key schedule from DES key.
|
||||
* Encrypt/Decrypt one 8-byte block.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
/* #define USE_INDEXING 1 */
|
||||
|
||||
/*
|
||||
* The tables below are the 8 sbox functions, with the 6-bit input permutation
|
||||
* and the 32-bit output permutation pre-computed.
|
||||
* They are shifted circularly to the left 3 bits, which removes 2 shifts
|
||||
* and an or from each round by reducing the number of sboxes whose
|
||||
* indices cross word broundaries from 2 to 1.
|
||||
*/
|
||||
|
||||
static const HALF SP[8][64] = {
|
||||
/* Box S1 */ {
|
||||
0x04041000, 0x00000000, 0x00040000, 0x04041010,
|
||||
0x04040010, 0x00041010, 0x00000010, 0x00040000,
|
||||
0x00001000, 0x04041000, 0x04041010, 0x00001000,
|
||||
0x04001010, 0x04040010, 0x04000000, 0x00000010,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00041000,
|
||||
0x00041000, 0x04040000, 0x04040000, 0x04001010,
|
||||
0x00040010, 0x04000010, 0x04000010, 0x00040010,
|
||||
0x00000000, 0x00001010, 0x00041010, 0x04000000,
|
||||
0x00040000, 0x04041010, 0x00000010, 0x04040000,
|
||||
0x04041000, 0x04000000, 0x04000000, 0x00001000,
|
||||
0x04040010, 0x00040000, 0x00041000, 0x04000010,
|
||||
0x00001000, 0x00000010, 0x04001010, 0x00041010,
|
||||
0x04041010, 0x00040010, 0x04040000, 0x04001010,
|
||||
0x04000010, 0x00001010, 0x00041010, 0x04041000,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00000000,
|
||||
0x00040010, 0x00041000, 0x00000000, 0x04040010
|
||||
},
|
||||
/* Box S2 */ {
|
||||
0x00420082, 0x00020002, 0x00020000, 0x00420080,
|
||||
0x00400000, 0x00000080, 0x00400082, 0x00020082,
|
||||
0x00000082, 0x00420082, 0x00420002, 0x00000002,
|
||||
0x00020002, 0x00400000, 0x00000080, 0x00400082,
|
||||
0x00420000, 0x00400080, 0x00020082, 0x00000000,
|
||||
0x00000002, 0x00020000, 0x00420080, 0x00400002,
|
||||
0x00400080, 0x00000082, 0x00000000, 0x00420000,
|
||||
0x00020080, 0x00420002, 0x00400002, 0x00020080,
|
||||
0x00000000, 0x00420080, 0x00400082, 0x00400000,
|
||||
0x00020082, 0x00400002, 0x00420002, 0x00020000,
|
||||
0x00400002, 0x00020002, 0x00000080, 0x00420082,
|
||||
0x00420080, 0x00000080, 0x00020000, 0x00000002,
|
||||
0x00020080, 0x00420002, 0x00400000, 0x00000082,
|
||||
0x00400080, 0x00020082, 0x00000082, 0x00400080,
|
||||
0x00420000, 0x00000000, 0x00020002, 0x00020080,
|
||||
0x00000002, 0x00400082, 0x00420082, 0x00420000
|
||||
},
|
||||
/* Box S3 */ {
|
||||
0x00000820, 0x20080800, 0x00000000, 0x20080020,
|
||||
0x20000800, 0x00000000, 0x00080820, 0x20000800,
|
||||
0x00080020, 0x20000020, 0x20000020, 0x00080000,
|
||||
0x20080820, 0x00080020, 0x20080000, 0x00000820,
|
||||
0x20000000, 0x00000020, 0x20080800, 0x00000800,
|
||||
0x00080800, 0x20080000, 0x20080020, 0x00080820,
|
||||
0x20000820, 0x00080800, 0x00080000, 0x20000820,
|
||||
0x00000020, 0x20080820, 0x00000800, 0x20000000,
|
||||
0x20080800, 0x20000000, 0x00080020, 0x00000820,
|
||||
0x00080000, 0x20080800, 0x20000800, 0x00000000,
|
||||
0x00000800, 0x00080020, 0x20080820, 0x20000800,
|
||||
0x20000020, 0x00000800, 0x00000000, 0x20080020,
|
||||
0x20000820, 0x00080000, 0x20000000, 0x20080820,
|
||||
0x00000020, 0x00080820, 0x00080800, 0x20000020,
|
||||
0x20080000, 0x20000820, 0x00000820, 0x20080000,
|
||||
0x00080820, 0x00000020, 0x20080020, 0x00080800
|
||||
},
|
||||
/* Box S4 */ {
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008200, 0x02000204, 0x02000004, 0x00008004,
|
||||
0x00000000, 0x02008000, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x02000200, 0x02000004,
|
||||
0x00000004, 0x00008000, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008004, 0x00008200,
|
||||
0x02000204, 0x00000004, 0x00008200, 0x02000200,
|
||||
0x00008000, 0x02008200, 0x02008204, 0x00000204,
|
||||
0x02000200, 0x02000004, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x00000000, 0x02008000,
|
||||
0x00008200, 0x02000200, 0x02000204, 0x00000004,
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008204, 0x00000204, 0x00000004, 0x00008000,
|
||||
0x02000004, 0x00008004, 0x02008200, 0x02000204,
|
||||
0x00008004, 0x00008200, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008000, 0x02008200
|
||||
},
|
||||
/* Box S5 */ {
|
||||
0x00000400, 0x08200400, 0x08200000, 0x08000401,
|
||||
0x00200000, 0x00000400, 0x00000001, 0x08200000,
|
||||
0x00200401, 0x00200000, 0x08000400, 0x00200401,
|
||||
0x08000401, 0x08200001, 0x00200400, 0x00000001,
|
||||
0x08000000, 0x00200001, 0x00200001, 0x00000000,
|
||||
0x00000401, 0x08200401, 0x08200401, 0x08000400,
|
||||
0x08200001, 0x00000401, 0x00000000, 0x08000001,
|
||||
0x08200400, 0x08000000, 0x08000001, 0x00200400,
|
||||
0x00200000, 0x08000401, 0x00000400, 0x08000000,
|
||||
0x00000001, 0x08200000, 0x08000401, 0x00200401,
|
||||
0x08000400, 0x00000001, 0x08200001, 0x08200400,
|
||||
0x00200401, 0x00000400, 0x08000000, 0x08200001,
|
||||
0x08200401, 0x00200400, 0x08000001, 0x08200401,
|
||||
0x08200000, 0x00000000, 0x00200001, 0x08000001,
|
||||
0x00200400, 0x08000400, 0x00000401, 0x00200000,
|
||||
0x00000000, 0x00200001, 0x08200400, 0x00000401
|
||||
},
|
||||
/* Box S6 */ {
|
||||
0x80000040, 0x81000000, 0x00010000, 0x81010040,
|
||||
0x81000000, 0x00000040, 0x81010040, 0x01000000,
|
||||
0x80010000, 0x01010040, 0x01000000, 0x80000040,
|
||||
0x01000040, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x00000000, 0x01000040, 0x80010040, 0x00010000,
|
||||
0x01010000, 0x80010040, 0x00000040, 0x81000040,
|
||||
0x81000040, 0x00000000, 0x01010040, 0x81010000,
|
||||
0x00010040, 0x01010000, 0x81010000, 0x80000000,
|
||||
0x80010000, 0x00000040, 0x81000040, 0x01010000,
|
||||
0x81010040, 0x01000000, 0x00010040, 0x80000040,
|
||||
0x01000000, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x80000040, 0x81010040, 0x01010000, 0x81000000,
|
||||
0x01010040, 0x81010000, 0x00000000, 0x81000040,
|
||||
0x00000040, 0x00010000, 0x81000000, 0x01010040,
|
||||
0x00010000, 0x01000040, 0x80010040, 0x00000000,
|
||||
0x81010000, 0x80000000, 0x01000040, 0x80010040
|
||||
},
|
||||
/* Box S7 */ {
|
||||
0x00800000, 0x10800008, 0x10002008, 0x00000000,
|
||||
0x00002000, 0x10002008, 0x00802008, 0x10802000,
|
||||
0x10802008, 0x00800000, 0x00000000, 0x10000008,
|
||||
0x00000008, 0x10000000, 0x10800008, 0x00002008,
|
||||
0x10002000, 0x00802008, 0x00800008, 0x10002000,
|
||||
0x10000008, 0x10800000, 0x10802000, 0x00800008,
|
||||
0x10800000, 0x00002000, 0x00002008, 0x10802008,
|
||||
0x00802000, 0x00000008, 0x10000000, 0x00802000,
|
||||
0x10000000, 0x00802000, 0x00800000, 0x10002008,
|
||||
0x10002008, 0x10800008, 0x10800008, 0x00000008,
|
||||
0x00800008, 0x10000000, 0x10002000, 0x00800000,
|
||||
0x10802000, 0x00002008, 0x00802008, 0x10802000,
|
||||
0x00002008, 0x10000008, 0x10802008, 0x10800000,
|
||||
0x00802000, 0x00000000, 0x00000008, 0x10802008,
|
||||
0x00000000, 0x00802008, 0x10800000, 0x00002000,
|
||||
0x10000008, 0x10002000, 0x00002000, 0x00800008
|
||||
},
|
||||
/* Box S8 */ {
|
||||
0x40004100, 0x00004000, 0x00100000, 0x40104100,
|
||||
0x40000000, 0x40004100, 0x00000100, 0x40000000,
|
||||
0x00100100, 0x40100000, 0x40104100, 0x00104000,
|
||||
0x40104000, 0x00104100, 0x00004000, 0x00000100,
|
||||
0x40100000, 0x40000100, 0x40004000, 0x00004100,
|
||||
0x00104000, 0x00100100, 0x40100100, 0x40104000,
|
||||
0x00004100, 0x00000000, 0x00000000, 0x40100100,
|
||||
0x40000100, 0x40004000, 0x00104100, 0x00100000,
|
||||
0x00104100, 0x00100000, 0x40104000, 0x00004000,
|
||||
0x00000100, 0x40100100, 0x00004000, 0x00104100,
|
||||
0x40004000, 0x00000100, 0x40000100, 0x40100000,
|
||||
0x40100100, 0x40000000, 0x00100000, 0x40004100,
|
||||
0x00000000, 0x40104100, 0x00100100, 0x40000100,
|
||||
0x40100000, 0x40004000, 0x40004100, 0x00000000,
|
||||
0x40104100, 0x00104000, 0x00104000, 0x00004100,
|
||||
0x00004100, 0x00100100, 0x40000000, 0x40104000
|
||||
}
|
||||
};
|
||||
|
||||
static const HALF PC2[8][64] = {
|
||||
/* table 0 */ {
|
||||
0x00000000, 0x00001000, 0x04000000, 0x04001000,
|
||||
0x00100000, 0x00101000, 0x04100000, 0x04101000,
|
||||
0x00008000, 0x00009000, 0x04008000, 0x04009000,
|
||||
0x00108000, 0x00109000, 0x04108000, 0x04109000,
|
||||
0x00000004, 0x00001004, 0x04000004, 0x04001004,
|
||||
0x00100004, 0x00101004, 0x04100004, 0x04101004,
|
||||
0x00008004, 0x00009004, 0x04008004, 0x04009004,
|
||||
0x00108004, 0x00109004, 0x04108004, 0x04109004,
|
||||
0x08000000, 0x08001000, 0x0c000000, 0x0c001000,
|
||||
0x08100000, 0x08101000, 0x0c100000, 0x0c101000,
|
||||
0x08008000, 0x08009000, 0x0c008000, 0x0c009000,
|
||||
0x08108000, 0x08109000, 0x0c108000, 0x0c109000,
|
||||
0x08000004, 0x08001004, 0x0c000004, 0x0c001004,
|
||||
0x08100004, 0x08101004, 0x0c100004, 0x0c101004,
|
||||
0x08008004, 0x08009004, 0x0c008004, 0x0c009004,
|
||||
0x08108004, 0x08109004, 0x0c108004, 0x0c109004
|
||||
},
|
||||
/* table 1 */ {
|
||||
0x00000000, 0x00002000, 0x80000000, 0x80002000,
|
||||
0x00000008, 0x00002008, 0x80000008, 0x80002008,
|
||||
0x00200000, 0x00202000, 0x80200000, 0x80202000,
|
||||
0x00200008, 0x00202008, 0x80200008, 0x80202008,
|
||||
0x20000000, 0x20002000, 0xa0000000, 0xa0002000,
|
||||
0x20000008, 0x20002008, 0xa0000008, 0xa0002008,
|
||||
0x20200000, 0x20202000, 0xa0200000, 0xa0202000,
|
||||
0x20200008, 0x20202008, 0xa0200008, 0xa0202008,
|
||||
0x00000400, 0x00002400, 0x80000400, 0x80002400,
|
||||
0x00000408, 0x00002408, 0x80000408, 0x80002408,
|
||||
0x00200400, 0x00202400, 0x80200400, 0x80202400,
|
||||
0x00200408, 0x00202408, 0x80200408, 0x80202408,
|
||||
0x20000400, 0x20002400, 0xa0000400, 0xa0002400,
|
||||
0x20000408, 0x20002408, 0xa0000408, 0xa0002408,
|
||||
0x20200400, 0x20202400, 0xa0200400, 0xa0202400,
|
||||
0x20200408, 0x20202408, 0xa0200408, 0xa0202408
|
||||
},
|
||||
/* table 2 */ {
|
||||
0x00000000, 0x00004000, 0x00000020, 0x00004020,
|
||||
0x00080000, 0x00084000, 0x00080020, 0x00084020,
|
||||
0x00000800, 0x00004800, 0x00000820, 0x00004820,
|
||||
0x00080800, 0x00084800, 0x00080820, 0x00084820,
|
||||
0x00000010, 0x00004010, 0x00000030, 0x00004030,
|
||||
0x00080010, 0x00084010, 0x00080030, 0x00084030,
|
||||
0x00000810, 0x00004810, 0x00000830, 0x00004830,
|
||||
0x00080810, 0x00084810, 0x00080830, 0x00084830,
|
||||
0x00400000, 0x00404000, 0x00400020, 0x00404020,
|
||||
0x00480000, 0x00484000, 0x00480020, 0x00484020,
|
||||
0x00400800, 0x00404800, 0x00400820, 0x00404820,
|
||||
0x00480800, 0x00484800, 0x00480820, 0x00484820,
|
||||
0x00400010, 0x00404010, 0x00400030, 0x00404030,
|
||||
0x00480010, 0x00484010, 0x00480030, 0x00484030,
|
||||
0x00400810, 0x00404810, 0x00400830, 0x00404830,
|
||||
0x00480810, 0x00484810, 0x00480830, 0x00484830
|
||||
},
|
||||
/* table 3 */ {
|
||||
0x00000000, 0x40000000, 0x00000080, 0x40000080,
|
||||
0x00040000, 0x40040000, 0x00040080, 0x40040080,
|
||||
0x00000040, 0x40000040, 0x000000c0, 0x400000c0,
|
||||
0x00040040, 0x40040040, 0x000400c0, 0x400400c0,
|
||||
0x10000000, 0x50000000, 0x10000080, 0x50000080,
|
||||
0x10040000, 0x50040000, 0x10040080, 0x50040080,
|
||||
0x10000040, 0x50000040, 0x100000c0, 0x500000c0,
|
||||
0x10040040, 0x50040040, 0x100400c0, 0x500400c0,
|
||||
0x00800000, 0x40800000, 0x00800080, 0x40800080,
|
||||
0x00840000, 0x40840000, 0x00840080, 0x40840080,
|
||||
0x00800040, 0x40800040, 0x008000c0, 0x408000c0,
|
||||
0x00840040, 0x40840040, 0x008400c0, 0x408400c0,
|
||||
0x10800000, 0x50800000, 0x10800080, 0x50800080,
|
||||
0x10840000, 0x50840000, 0x10840080, 0x50840080,
|
||||
0x10800040, 0x50800040, 0x108000c0, 0x508000c0,
|
||||
0x10840040, 0x50840040, 0x108400c0, 0x508400c0
|
||||
},
|
||||
/* table 4 */ {
|
||||
0x00000000, 0x00000008, 0x08000000, 0x08000008,
|
||||
0x00040000, 0x00040008, 0x08040000, 0x08040008,
|
||||
0x00002000, 0x00002008, 0x08002000, 0x08002008,
|
||||
0x00042000, 0x00042008, 0x08042000, 0x08042008,
|
||||
0x80000000, 0x80000008, 0x88000000, 0x88000008,
|
||||
0x80040000, 0x80040008, 0x88040000, 0x88040008,
|
||||
0x80002000, 0x80002008, 0x88002000, 0x88002008,
|
||||
0x80042000, 0x80042008, 0x88042000, 0x88042008,
|
||||
0x00080000, 0x00080008, 0x08080000, 0x08080008,
|
||||
0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008,
|
||||
0x00082000, 0x00082008, 0x08082000, 0x08082008,
|
||||
0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008,
|
||||
0x80080000, 0x80080008, 0x88080000, 0x88080008,
|
||||
0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008,
|
||||
0x80082000, 0x80082008, 0x88082000, 0x88082008,
|
||||
0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008
|
||||
},
|
||||
/* table 5 */ {
|
||||
0x00000000, 0x00400000, 0x00008000, 0x00408000,
|
||||
0x40000000, 0x40400000, 0x40008000, 0x40408000,
|
||||
0x00000020, 0x00400020, 0x00008020, 0x00408020,
|
||||
0x40000020, 0x40400020, 0x40008020, 0x40408020,
|
||||
0x00001000, 0x00401000, 0x00009000, 0x00409000,
|
||||
0x40001000, 0x40401000, 0x40009000, 0x40409000,
|
||||
0x00001020, 0x00401020, 0x00009020, 0x00409020,
|
||||
0x40001020, 0x40401020, 0x40009020, 0x40409020,
|
||||
0x00100000, 0x00500000, 0x00108000, 0x00508000,
|
||||
0x40100000, 0x40500000, 0x40108000, 0x40508000,
|
||||
0x00100020, 0x00500020, 0x00108020, 0x00508020,
|
||||
0x40100020, 0x40500020, 0x40108020, 0x40508020,
|
||||
0x00101000, 0x00501000, 0x00109000, 0x00509000,
|
||||
0x40101000, 0x40501000, 0x40109000, 0x40509000,
|
||||
0x00101020, 0x00501020, 0x00109020, 0x00509020,
|
||||
0x40101020, 0x40501020, 0x40109020, 0x40509020
|
||||
},
|
||||
/* table 6 */ {
|
||||
0x00000000, 0x00000040, 0x04000000, 0x04000040,
|
||||
0x00000800, 0x00000840, 0x04000800, 0x04000840,
|
||||
0x00800000, 0x00800040, 0x04800000, 0x04800040,
|
||||
0x00800800, 0x00800840, 0x04800800, 0x04800840,
|
||||
0x10000000, 0x10000040, 0x14000000, 0x14000040,
|
||||
0x10000800, 0x10000840, 0x14000800, 0x14000840,
|
||||
0x10800000, 0x10800040, 0x14800000, 0x14800040,
|
||||
0x10800800, 0x10800840, 0x14800800, 0x14800840,
|
||||
0x00000080, 0x000000c0, 0x04000080, 0x040000c0,
|
||||
0x00000880, 0x000008c0, 0x04000880, 0x040008c0,
|
||||
0x00800080, 0x008000c0, 0x04800080, 0x048000c0,
|
||||
0x00800880, 0x008008c0, 0x04800880, 0x048008c0,
|
||||
0x10000080, 0x100000c0, 0x14000080, 0x140000c0,
|
||||
0x10000880, 0x100008c0, 0x14000880, 0x140008c0,
|
||||
0x10800080, 0x108000c0, 0x14800080, 0x148000c0,
|
||||
0x10800880, 0x108008c0, 0x14800880, 0x148008c0
|
||||
},
|
||||
/* table 7 */ {
|
||||
0x00000000, 0x00000010, 0x00000400, 0x00000410,
|
||||
0x00000004, 0x00000014, 0x00000404, 0x00000414,
|
||||
0x00004000, 0x00004010, 0x00004400, 0x00004410,
|
||||
0x00004004, 0x00004014, 0x00004404, 0x00004414,
|
||||
0x20000000, 0x20000010, 0x20000400, 0x20000410,
|
||||
0x20000004, 0x20000014, 0x20000404, 0x20000414,
|
||||
0x20004000, 0x20004010, 0x20004400, 0x20004410,
|
||||
0x20004004, 0x20004014, 0x20004404, 0x20004414,
|
||||
0x00200000, 0x00200010, 0x00200400, 0x00200410,
|
||||
0x00200004, 0x00200014, 0x00200404, 0x00200414,
|
||||
0x00204000, 0x00204010, 0x00204400, 0x00204410,
|
||||
0x00204004, 0x00204014, 0x00204404, 0x00204414,
|
||||
0x20200000, 0x20200010, 0x20200400, 0x20200410,
|
||||
0x20200004, 0x20200014, 0x20200404, 0x20200414,
|
||||
0x20204000, 0x20204010, 0x20204400, 0x20204410,
|
||||
0x20204004, 0x20204014, 0x20204404, 0x20204414
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The PC-1 Permutation
|
||||
* If we number the bits of the 8 bytes of key input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the PC-1 permutation,
|
||||
* C0 is
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43
|
||||
* D0 is
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 33 23 13 03
|
||||
* and these parity bits have been discarded:
|
||||
* 77 67 57 47 37 27 17 07
|
||||
*
|
||||
* We achieve this by flipping the input matrix about the diagonal from 70-07,
|
||||
* getting left =
|
||||
* 77 67 57 47 37 27 17 07 (these are the parity bits)
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* right =
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* then byte swap right, ala htonl() on a little endian machine.
|
||||
* right =
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 67 57 47 37 27 11 07
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* then
|
||||
* c0 = right >> 4;
|
||||
* d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
*/
|
||||
|
||||
#define FLIP_RIGHT_DIAGONAL(word, temp) \
|
||||
temp = (word ^ (word >> 18)) & 0x00003333; \
|
||||
word ^= temp | (temp << 18); \
|
||||
temp = (word ^ (word >> 9)) & 0x00550055; \
|
||||
word ^= temp | (temp << 9);
|
||||
|
||||
#if defined(__GNUC__) && defined(NSS_X86_OR_X64)
|
||||
#define BYTESWAP(word, temp) \
|
||||
__asm("bswap %0" : "+r" (word));
|
||||
#elif (_MSC_VER >= 1300) && defined(NSS_X86_OR_X64)
|
||||
#include <stdlib.h>
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#define BYTESWAP(word, temp) \
|
||||
word = _byteswap_ulong(word);
|
||||
#else
|
||||
#define BYTESWAP(word, temp) \
|
||||
word = (word >> 16) | (word << 16); \
|
||||
temp = 0x00ff00ff; \
|
||||
word = ((word & temp) << 8) | ((word >> 8) & temp);
|
||||
#endif
|
||||
|
||||
#define PC1(left, right, c0, d0, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
FLIP_RIGHT_DIAGONAL(left, temp); \
|
||||
FLIP_RIGHT_DIAGONAL(right, temp); \
|
||||
BYTESWAP(right, temp); \
|
||||
c0 = right >> 4; \
|
||||
d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
|
||||
#define LEFT_SHIFT_1( reg ) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
|
||||
#define LEFT_SHIFT_2( reg ) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
|
||||
|
||||
/*
|
||||
* setup key schedules from key
|
||||
*/
|
||||
|
||||
void
|
||||
DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF c0, d0;
|
||||
register HALF temp;
|
||||
int delta;
|
||||
unsigned int ls;
|
||||
|
||||
#if defined(NSS_X86_OR_X64)
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)key & 0x03) == 0) {
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) |
|
||||
((HALF)key[2] << 8) | key[3];
|
||||
right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) |
|
||||
((HALF)key[6] << 8) | key[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
PC1(left, right, c0, d0, temp);
|
||||
|
||||
if (direction == DES_ENCRYPT) {
|
||||
delta = 2 * (int)sizeof(HALF);
|
||||
} else {
|
||||
ks += 30;
|
||||
delta = (-2) * (int)sizeof(HALF);
|
||||
}
|
||||
|
||||
for (ls = 0x8103; ls; ls >>= 1) {
|
||||
if ( ls & 1 ) {
|
||||
c0 = LEFT_SHIFT_1( c0 );
|
||||
d0 = LEFT_SHIFT_1( d0 );
|
||||
} else {
|
||||
c0 = LEFT_SHIFT_2( c0 );
|
||||
d0 = LEFT_SHIFT_2( d0 );
|
||||
}
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define PC2LOOKUP(b,c) PC2[b][c]
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7) );
|
||||
left |= PC2LOOKUP(3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F) );
|
||||
right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
|
||||
#else
|
||||
#define PC2LOOKUP(b,c) *(HALF *)((BYTE *)&PC2[b][0]+(c))
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C) );
|
||||
left |= PC2LOOKUP(3, ((c0>>16)&0x30)|((c0>>9)&0xC)|((c0<<2)&0xC0));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC) );
|
||||
right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
|
||||
#endif
|
||||
/* left contains key bits for S1 S3 S2 S4 */
|
||||
/* right contains key bits for S6 S8 S5 S7 */
|
||||
temp = (left << 16) /* S2 S4 XX XX */
|
||||
| (right >> 16); /* XX XX S6 S8 */
|
||||
ks[0] = temp;
|
||||
|
||||
temp = (left & 0xffff0000) /* S1 S3 XX XX */
|
||||
| (right & 0x0000ffff);/* XX XX S5 S7 */
|
||||
ks[1] = temp;
|
||||
|
||||
ks = (HALF*)((BYTE *)ks + delta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The DES Initial Permutation
|
||||
* if we number the bits of the 8 bytes of input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the initial permutation, they will be in this order.
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 77 67 57 47 37 27 17 07
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 76 66 56 46 36 26 16 06
|
||||
*
|
||||
* One way to do this is in two steps:
|
||||
* 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
|
||||
* 2. Rearrange the bytes (rows in the matrix above) with the following code.
|
||||
*
|
||||
* #define swapHiLo(word, temp) \
|
||||
* temp = (word ^ (word >> 24)) & 0x000000ff; \
|
||||
* word ^= temp | (temp << 24);
|
||||
*
|
||||
* right ^= temp = ((left << 8) ^ right) & 0xff00ff00;
|
||||
* left ^= temp >> 8;
|
||||
* swapHiLo(left, temp);
|
||||
* swapHiLo(right,temp);
|
||||
*
|
||||
* However, the two steps can be combined, so that the rows are rearranged
|
||||
* while the matrix is being flipped, reducing the number of bit exchange
|
||||
* operations from 8 ot 5.
|
||||
*
|
||||
* Initial Permutation */
|
||||
#define IP(left, right, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1;
|
||||
|
||||
/* The Final (Inverse Initial) permutation is done by reversing the
|
||||
** steps of the Initital Permutation
|
||||
*/
|
||||
|
||||
#define FP(left, right, temp) \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4;
|
||||
|
||||
void
|
||||
DES_Do1Block(HALF * ks, const BYTE * inbuf, BYTE * outbuf)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF temp;
|
||||
|
||||
#if defined(NSS_X86_OR_X64)
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)inbuf & 0x03) == 0) {
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) |
|
||||
((HALF)inbuf[2] << 8) | inbuf[3];
|
||||
right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) |
|
||||
((HALF)inbuf[6] << 8) | inbuf[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
IP(left, right, temp);
|
||||
|
||||
/* shift the values left circularly 3 bits. */
|
||||
left = (left << 3) | (left >> 29);
|
||||
right = (right << 3) | (right >> 29);
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define KSLOOKUP(s,b) SP[s][((temp >> (b+2)) & 0x3f)]
|
||||
#else
|
||||
#define KSLOOKUP(s,b) *(HALF*)((BYTE*)&SP[s][0]+((temp >> b) & 0xFC))
|
||||
#endif
|
||||
#define ROUND(out, in, r) \
|
||||
temp = in ^ ks[2*r]; \
|
||||
out ^= KSLOOKUP( 1, 24 ); \
|
||||
out ^= KSLOOKUP( 3, 16 ); \
|
||||
out ^= KSLOOKUP( 5, 8 ); \
|
||||
out ^= KSLOOKUP( 7, 0 ); \
|
||||
temp = ((in >> 4) | (in << 28)) ^ ks[2*r+1]; \
|
||||
out ^= KSLOOKUP( 0, 24 ); \
|
||||
out ^= KSLOOKUP( 2, 16 ); \
|
||||
out ^= KSLOOKUP( 4, 8 ); \
|
||||
out ^= KSLOOKUP( 6, 0 );
|
||||
|
||||
/* Do the 16 Feistel rounds */
|
||||
ROUND(left, right, 0)
|
||||
ROUND(right, left, 1)
|
||||
ROUND(left, right, 2)
|
||||
ROUND(right, left, 3)
|
||||
ROUND(left, right, 4)
|
||||
ROUND(right, left, 5)
|
||||
ROUND(left, right, 6)
|
||||
ROUND(right, left, 7)
|
||||
ROUND(left, right, 8)
|
||||
ROUND(right, left, 9)
|
||||
ROUND(left, right, 10)
|
||||
ROUND(right, left, 11)
|
||||
ROUND(left, right, 12)
|
||||
ROUND(right, left, 13)
|
||||
ROUND(left, right, 14)
|
||||
ROUND(right, left, 15)
|
||||
|
||||
/* now shift circularly right 3 bits to undo the shifting done
|
||||
** above. switch left and right here.
|
||||
*/
|
||||
temp = (left >> 3) | (left << 29);
|
||||
left = (right >> 3) | (right << 29);
|
||||
right = temp;
|
||||
|
||||
FP(left, right, temp);
|
||||
|
||||
#if defined(NSS_X86_OR_X64)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
#else
|
||||
if (((ptrdiff_t)outbuf & 0x03) == 0) {
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
} else {
|
||||
outbuf[0] = (BYTE)(left >> 24);
|
||||
outbuf[1] = (BYTE)(left >> 16);
|
||||
outbuf[2] = (BYTE)(left >> 8);
|
||||
outbuf[3] = (BYTE)(left );
|
||||
|
||||
outbuf[4] = (BYTE)(right >> 24);
|
||||
outbuf[5] = (BYTE)(right >> 16);
|
||||
outbuf[6] = (BYTE)(right >> 8);
|
||||
outbuf[7] = (BYTE)(right );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Ackowledgements:
|
||||
** Two ideas used in this implementation were shown to me by Dennis Ferguson
|
||||
** in 1990. He credits them to Richard Outerbridge and Dan Hoey. They were:
|
||||
** 1. The method of computing the Initial and Final permutations.
|
||||
** 2. Circularly rotating the SP tables and the initial values of left and
|
||||
** right to reduce the number of shifts required during the 16 rounds.
|
||||
*/
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* des.h
|
||||
*
|
||||
* header file for DES-150 library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _DES_H_
|
||||
#define _DES_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned int HALF;
|
||||
|
||||
#define HALFPTR(x) ((HALF *)(x))
|
||||
#define SHORTPTR(x) ((unsigned short *)(x))
|
||||
#define BYTEPTR(x) ((BYTE *)(x))
|
||||
|
||||
typedef enum {
|
||||
DES_ENCRYPT = 0x5555,
|
||||
DES_DECRYPT = 0xAAAA
|
||||
} DESDirection;
|
||||
|
||||
typedef void DESFunc(struct DESContextStr *cx, BYTE *out, const BYTE *in,
|
||||
unsigned int len);
|
||||
|
||||
struct DESContextStr {
|
||||
/* key schedule, 16 internal keys, each with 8 6-bit parts */
|
||||
HALF ks0 [32];
|
||||
HALF ks1 [32];
|
||||
HALF ks2 [32];
|
||||
HALF iv [2];
|
||||
DESDirection direction;
|
||||
DESFunc *worker;
|
||||
};
|
||||
|
||||
void DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction);
|
||||
void DES_Do1Block( HALF * ks, const BYTE * inbuf, BYTE * outbuf);
|
||||
|
||||
#endif
|
||||
@@ -1,305 +0,0 @@
|
||||
/*
|
||||
* desblapi.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Implement DES Modes of Operation and Triple-DES.
|
||||
* Adapt DES-150 to blapi API.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h>
|
||||
#include "secerr.h"
|
||||
|
||||
#if defined(NSS_X86_OR_X64)
|
||||
/* Intel X86 CPUs do unaligned loads and stores without complaint. */
|
||||
#define COPY8B(to, from, ptr) \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1];
|
||||
#elif defined(USE_MEMCPY)
|
||||
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
|
||||
#else
|
||||
#define COPY8B(to, from, ptr) \
|
||||
if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1]; \
|
||||
} else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
|
||||
SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
|
||||
SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
|
||||
SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
|
||||
SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
|
||||
} else { \
|
||||
BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
|
||||
BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
|
||||
BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
|
||||
BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
|
||||
BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
|
||||
BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
|
||||
BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
|
||||
BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
|
||||
}
|
||||
#endif
|
||||
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
|
||||
#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
|
||||
|
||||
static void
|
||||
DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks1, out, out);
|
||||
DES_Do1Block(cx->ks2, out, out);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
DESContext *
|
||||
DES_AllocateContext(void)
|
||||
{
|
||||
return PORT_ZNew(DESContext);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
|
||||
const unsigned char *iv, int mode, unsigned int encrypt,
|
||||
unsigned int unused)
|
||||
{
|
||||
DESDirection opposite;
|
||||
if (!cx) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
|
||||
opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
|
||||
switch (mode) {
|
||||
case NSS_DES: /* DES ECB */
|
||||
DES_MakeSchedule( cx->ks0, key, cx->direction);
|
||||
cx->worker = &DES_ECB;
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3: /* DES EDE ECB */
|
||||
cx->worker = &DES_EDE3_ECB;
|
||||
if (encrypt) {
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSS_DES_CBC: /* DES CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3_CBC: /* DES EDE CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
if (encrypt) {
|
||||
cx->worker = &DES_EDE3CBCEn;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
cx->worker = &DES_EDE3CBCDe;
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
DESContext *
|
||||
DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
|
||||
{
|
||||
DESContext *cx = PORT_ZNew(DESContext);
|
||||
SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
PORT_ZFree(cx, sizeof *cx);
|
||||
cx = NULL;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
DES_DestroyContext(DESContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_ENCRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_DECRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Diffie-Hellman parameter generation, key generation, and secret derivation.
|
||||
* KEA secret generation and verification.
|
||||
*
|
||||
* $Id: dh.c,v 1.8.8.1 2010-03-15 07:03:23 nelson%bolyard.com Exp $
|
||||
*/
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secitem.h"
|
||||
#include "mpi.h"
|
||||
#include "mpprime.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
#define DH_SECRET_KEY_LEN 20
|
||||
#define KEA_DERIVED_SECRET_LEN 128
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams **params)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHParams *dhparams;
|
||||
unsigned char *pb = NULL;
|
||||
unsigned char *ab = NULL;
|
||||
unsigned long counter = 0;
|
||||
mp_int p, q, a, h, psub1, test;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || primeLen < 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
|
||||
if (!dhparams) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams->arena = arena;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
MP_DIGITS(&h) = 0;
|
||||
MP_DIGITS(&psub1) = 0;
|
||||
MP_DIGITS(&test) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
CHECK_MPI_OK( mp_init(&h) );
|
||||
CHECK_MPI_OK( mp_init(&psub1) );
|
||||
CHECK_MPI_OK( mp_init(&test) );
|
||||
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
|
||||
pb = PORT_Alloc(primeLen);
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
|
||||
pb[0] |= 0x80; /* set high-order bit */
|
||||
pb[primeLen-1] |= 0x01; /* set low-order bit */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
|
||||
CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
|
||||
/* construct Sophie-Germain prime q = (p-1)/2. */
|
||||
CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
|
||||
CHECK_MPI_OK( mp_div_2(&psub1, &q) );
|
||||
/* construct a generator from the prime. */
|
||||
ab = PORT_Alloc(primeLen);
|
||||
/* generate a candidate number a in p's field */
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
|
||||
/* force a < p (note that quot(a/p) <= 1) */
|
||||
if ( mp_cmp(&a, &p) > 0 )
|
||||
CHECK_MPI_OK( mp_sub(&a, &p, &a) );
|
||||
do {
|
||||
/* check that a is in the range [2..p-1] */
|
||||
if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
|
||||
/* a is outside of the allowed range. Set a=3 and keep going. */
|
||||
mp_set(&a, 3);
|
||||
}
|
||||
/* if a**q mod p != 1 then a is a generator */
|
||||
CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
|
||||
if ( mp_cmp_d(&test, 1) != 0 )
|
||||
break;
|
||||
/* increment the candidate and try again. */
|
||||
CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
|
||||
} while (PR_TRUE);
|
||||
MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
|
||||
MPINT_TO_SECITEM(&a, &dhparams->base, arena);
|
||||
*params = dhparams;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&a);
|
||||
mp_clear(&h);
|
||||
mp_clear(&psub1);
|
||||
mp_clear(&test);
|
||||
if (pb) PORT_ZFree(pb, primeLen);
|
||||
if (ab) PORT_ZFree(ab, primeLen);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHPrivateKey *key;
|
||||
mp_int g, xa, p, Ya;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->arena = arena;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&xa) = 0;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Ya) = 0;
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&xa) );
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Ya) );
|
||||
/* Set private key's p */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) );
|
||||
SECITEM_TO_MPINT(key->prime, &p);
|
||||
/* Set private key's g */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) );
|
||||
SECITEM_TO_MPINT(key->base, &g);
|
||||
/* Generate private key xa */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DH_SECRET_KEY_LEN);
|
||||
RNG_GenerateGlobalRandomBytes(key->privateValue.data,
|
||||
key->privateValue.len);
|
||||
SECITEM_TO_MPINT( key->privateValue, &xa );
|
||||
/* xa < p */
|
||||
CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
|
||||
/* Compute public key Ya = g ** xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
|
||||
MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
|
||||
*privKey = key;
|
||||
cleanup:
|
||||
mp_clear(&g);
|
||||
mp_clear(&xa);
|
||||
mp_clear(&p);
|
||||
mp_clear(&Ya);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem *publicValue,
|
||||
SECItem *prime,
|
||||
SECItem *privateValue,
|
||||
SECItem *derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
mp_int p, Xa, Yb, ZZ;
|
||||
mp_err err = MP_OKAY;
|
||||
int len = 0;
|
||||
unsigned int nb;
|
||||
unsigned char *secret = NULL;
|
||||
if (!publicValue || !prime || !privateValue || !derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Xa) = 0;
|
||||
MP_DIGITS(&Yb) = 0;
|
||||
MP_DIGITS(&ZZ) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Xa) );
|
||||
CHECK_MPI_OK( mp_init(&Yb) );
|
||||
CHECK_MPI_OK( mp_init(&ZZ) );
|
||||
SECITEM_TO_MPINT(*publicValue, &Yb);
|
||||
SECITEM_TO_MPINT(*privateValue, &Xa);
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
/* ZZ = (Yb)**Xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );
|
||||
/* number of bytes in the derived secret */
|
||||
len = mp_unsigned_octet_size(&ZZ);
|
||||
if (len <= 0) {
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
}
|
||||
/* allocate a buffer which can hold the entire derived secret. */
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the derived secret */
|
||||
err = mp_to_unsigned_octets(&ZZ, secret, len);
|
||||
if (err >= 0) err = MP_OKAY;
|
||||
/* Take minimum of bytes requested and bytes in derived secret,
|
||||
** if maxOutBytes is 0 take all of the bytes from the derived secret.
|
||||
*/
|
||||
if (maxOutBytes > 0)
|
||||
nb = PR_MIN(len, maxOutBytes);
|
||||
else
|
||||
nb = len;
|
||||
SECITEM_AllocItem(NULL, derivedSecret, nb);
|
||||
memcpy(derivedSecret->data, secret, nb);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Xa);
|
||||
mp_clear(&Yb);
|
||||
mp_clear(&ZZ);
|
||||
if (secret) {
|
||||
/* free the buffer allocated for the full secret. */
|
||||
PORT_ZFree(secret, len);
|
||||
}
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
if (derivedSecret->data)
|
||||
PORT_ZFree(derivedSecret->data, derivedSecret->len);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
KEA_Derive(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
mp_int p, Y, R, r, x, t, u, w;
|
||||
mp_err err;
|
||||
unsigned char *secret = NULL;
|
||||
unsigned int len = 0, offset;
|
||||
if (!prime || !public1 || !public2 || !private1 || !private2 ||
|
||||
!derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Y) = 0;
|
||||
MP_DIGITS(&R) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&t) = 0;
|
||||
MP_DIGITS(&u) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Y) );
|
||||
CHECK_MPI_OK( mp_init(&R) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&t) );
|
||||
CHECK_MPI_OK( mp_init(&u) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*public1, &Y);
|
||||
SECITEM_TO_MPINT(*public2, &R);
|
||||
SECITEM_TO_MPINT(*private1, &r);
|
||||
SECITEM_TO_MPINT(*private2, &x);
|
||||
/* t = DH(Y, r, p) = Y ** r mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) );
|
||||
/* u = DH(R, x, p) = R ** x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) );
|
||||
/* w = (t + u) mod p */
|
||||
CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) );
|
||||
/* allocate a buffer for the full derived secret */
|
||||
len = mp_unsigned_octet_size(&w);
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the secret */
|
||||
err = mp_to_unsigned_octets(&w, secret, len);
|
||||
if (err > 0) err = MP_OKAY;
|
||||
/* allocate output buffer */
|
||||
SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
|
||||
memset(derivedSecret->data, 0, derivedSecret->len);
|
||||
/* copy in the 128 lsb of the secret */
|
||||
if (len >= KEA_DERIVED_SECRET_LEN) {
|
||||
memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN),
|
||||
KEA_DERIVED_SECRET_LEN);
|
||||
} else {
|
||||
offset = KEA_DERIVED_SECRET_LEN - len;
|
||||
memcpy(derivedSecret->data + offset, secret, len);
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Y);
|
||||
mp_clear(&R);
|
||||
mp_clear(&r);
|
||||
mp_clear(&x);
|
||||
mp_clear(&t);
|
||||
mp_clear(&u);
|
||||
mp_clear(&w);
|
||||
if (secret)
|
||||
PORT_ZFree(secret, len);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
mp_int p, q, y, r;
|
||||
mp_err err;
|
||||
int cmp = 1; /* default is false */
|
||||
if (!Y || !prime || !subPrime) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*subPrime, &q);
|
||||
SECITEM_TO_MPINT(*Y, &y);
|
||||
/* compute r = y**q mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) );
|
||||
/* compare to 1 */
|
||||
cmp = mp_cmp_d(&r, 1);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return (cmp == 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
@@ -1,729 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Network Security Services libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Portions created by Netscape Communications Corporation
|
||||
* are Copyright (C) 1994-2000 Netscape Communications Corporation.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: drbg.c,v 1.9 2009-06-10 03:24:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "prerror.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prinit.h"
|
||||
#include "blapi.h"
|
||||
#include "blapii.h"
|
||||
#include "nssilock.h"
|
||||
#include "secitem.h"
|
||||
#include "sha_fast.h"
|
||||
#include "sha256.h"
|
||||
#include "secrng.h" /* for RNG_SystemRNG() */
|
||||
#include "secmpi.h"
|
||||
|
||||
/* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1
|
||||
* for SHA-1, SHA-224, and SHA-256 it's 440 bits.
|
||||
* for SHA-384 and SHA-512 it's 888 bits */
|
||||
#define PRNG_SEEDLEN (440/PR_BITS_PER_BYTE)
|
||||
static const PRInt64 PRNG_MAX_ADDITIONAL_BYTES = LL_INIT(0x1, 0x0);
|
||||
/* 2^35 bits or 2^32 bytes */
|
||||
#define PRNG_MAX_REQUEST_SIZE 0x10000 /* 2^19 bits or 2^16 bytes */
|
||||
#define PRNG_ADDITONAL_DATA_CACHE_SIZE (8*1024) /* must be less than
|
||||
* PRNG_MAX_ADDITIONAL_BYTES
|
||||
*/
|
||||
|
||||
|
||||
/* RESEED_COUNT is how many calls to the prng before we need to reseed
|
||||
* under normal NIST rules, you must return an error. In the NSS case, we
|
||||
* self-reseed with RNG_SystemRNG(). Count can be a large number. For code
|
||||
* simplicity, we specify count with 2 components: RESEED_BYTE (which is
|
||||
* the same as LOG256(RESEED_COUNT)) and RESEED_VALUE (which is the same as
|
||||
* RESEED_COUNT / (256 ^ RESEED_BYTE)). Another way to look at this is
|
||||
* RESEED_COUNT = RESEED_VALUE * (256 ^ RESEED_BYTE). For Hash based DRBG
|
||||
* we use the maximum count value, 2^48, or RESEED_BYTE=6 and RESEED_VALUE=1
|
||||
*/
|
||||
#define RESEED_BYTE 6
|
||||
#define RESEED_VALUE 1
|
||||
|
||||
#define PRNG_RESET_RESEED_COUNT(rng) \
|
||||
PORT_Memset((rng)->reseed_counter, 0, sizeof (rng)->reseed_counter); \
|
||||
(rng)->reseed_counter[RESEED_BYTE] = 1;
|
||||
|
||||
|
||||
/*
|
||||
* The actual values of this enum are specified in SP 800-90, 10.1.1.*
|
||||
* The spec does not name the types, it only uses bare values
|
||||
*/
|
||||
typedef enum {
|
||||
prngCGenerateType = 0, /* used when creating a new 'C' */
|
||||
prngReseedType = 1, /* used in reseeding */
|
||||
prngAdditionalDataType = 2, /* used in mixing additional data */
|
||||
prngGenerateByteType = 3 /* used when mixing internal state while
|
||||
* generating bytes */
|
||||
} prngVTypes;
|
||||
|
||||
/*
|
||||
* Global RNG context
|
||||
*/
|
||||
struct RNGContextStr {
|
||||
PZLock *lock; /* Lock to serialize access to global rng */
|
||||
/*
|
||||
* NOTE, a number of steps in the drbg algorithm need to hash
|
||||
* V_type || V. The code, therefore, depends on the V array following
|
||||
* immediately after V_type to avoid extra copies. To accomplish this
|
||||
* in a way that compiliers can't perturb, we declare V_type and V
|
||||
* as a V_Data array and reference them by macros */
|
||||
PRUint8 V_Data[PRNG_SEEDLEN+1]; /* internal state variables */
|
||||
#define V_type V_Data[0]
|
||||
#define V(rng) (((rng)->V_Data)+1)
|
||||
#define VSize(rng) ((sizeof (rng)->V_Data) -1)
|
||||
PRUint8 C[PRNG_SEEDLEN]; /* internal state variables */
|
||||
PRUint8 oldV[PRNG_SEEDLEN]; /* for continuous rng checking */
|
||||
/* If we get calls for the PRNG to return less than the length of our
|
||||
* hash, we extend the request for a full hash (since we'll be doing
|
||||
* the full hash anyway). Future requests for random numbers are fulfilled
|
||||
* from the remainder of the bytes we generated. Requests for bytes longer
|
||||
* than the hash size are fulfilled directly from the HashGen function
|
||||
* of the random number generator. */
|
||||
PRUint8 reseed_counter[RESEED_BYTE+1]; /* number of requests since the
|
||||
* last reseed. Need only be
|
||||
* big enough to hold the whole
|
||||
* reseed count */
|
||||
PRUint8 data[SHA256_LENGTH]; /* when we request less than a block
|
||||
* save the rest of the rng output for
|
||||
* another partial block */
|
||||
PRUint8 dataAvail; /* # bytes of output available in our cache,
|
||||
* [0...SHA256_LENGTH] */
|
||||
/* store additional data that has been shovelled off to us by
|
||||
* RNG_RandomUpdate. */
|
||||
PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
|
||||
PRUint32 additionalAvail;
|
||||
PRBool isValid; /* false if RNG reaches an invalid state */
|
||||
};
|
||||
|
||||
typedef struct RNGContextStr RNGContext;
|
||||
static RNGContext *globalrng = NULL;
|
||||
static RNGContext theGlobalRng;
|
||||
|
||||
|
||||
/*
|
||||
* The next several functions are derived from the NIST SP 800-90
|
||||
* spec. In these functions, an attempt was made to use names consistent
|
||||
* with the names in the spec, even if they differ from normal NSS usage.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hash Derive function defined in NISP SP 800-90 Section 10.4.1.
|
||||
* This function is used in the Instantiate and Reseed functions.
|
||||
*
|
||||
* NOTE: requested_bytes cannot overlap with input_string_1 or input_string_2.
|
||||
* input_string_1 and input_string_2 are logically concatentated.
|
||||
* input_string_1 must be supplied.
|
||||
* if input_string_2 is not supplied, NULL should be passed for this parameter.
|
||||
*/
|
||||
static SECStatus
|
||||
prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
|
||||
const PRUint8 *input_string_1, unsigned int input_string_1_len,
|
||||
const PRUint8 *input_string_2, unsigned int input_string_2_len)
|
||||
{
|
||||
SHA256Context ctx;
|
||||
PRUint32 tmp;
|
||||
PRUint8 counter;
|
||||
|
||||
tmp=SHA_HTONL(no_of_bytes_to_return*8);
|
||||
|
||||
for (counter = 1 ; no_of_bytes_to_return > 0; counter++) {
|
||||
unsigned int hash_return_len;
|
||||
SHA256_Begin(&ctx);
|
||||
SHA256_Update(&ctx, &counter, 1);
|
||||
SHA256_Update(&ctx, (unsigned char *)&tmp, sizeof tmp);
|
||||
SHA256_Update(&ctx, input_string_1, input_string_1_len);
|
||||
if (input_string_2) {
|
||||
SHA256_Update(&ctx, input_string_2, input_string_2_len);
|
||||
}
|
||||
SHA256_End(&ctx, requested_bytes, &hash_return_len,
|
||||
no_of_bytes_to_return);
|
||||
requested_bytes += hash_return_len;
|
||||
no_of_bytes_to_return -= hash_return_len;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
|
||||
*
|
||||
* NOTE: bytes & len are entropy || nonce || personalization_string. In
|
||||
* normal operation, NSS calculates them all together in a single call.
|
||||
*/
|
||||
static SECStatus
|
||||
prng_instantiate(RNGContext *rng, PRUint8 *bytes, unsigned int len)
|
||||
{
|
||||
prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
|
||||
rng->V_type = prngCGenerateType;
|
||||
prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
|
||||
PRNG_RESET_RESEED_COUNT(rng)
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update the global random number generator with more seeding
|
||||
* material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
|
||||
* section 10.1.1.3
|
||||
*
|
||||
* If entropy is NULL, it is fetched from the noise generator.
|
||||
*/
|
||||
static
|
||||
SECStatus
|
||||
prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
|
||||
const PRUint8 *additional_input, unsigned int additional_input_len)
|
||||
{
|
||||
PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN];
|
||||
PRUint8 *noise = &noiseData[0];
|
||||
|
||||
/* if entropy wasn't supplied, fetch it. (normal operation case) */
|
||||
if (entropy == NULL) {
|
||||
entropy_len = (unsigned int) RNG_SystemRNG(
|
||||
&noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
|
||||
} else {
|
||||
/* NOTE: this code is only available for testing, not to applications */
|
||||
/* if entropy was too big for the stack variable, get it from malloc */
|
||||
if (entropy_len > PRNG_SEEDLEN) {
|
||||
noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data));
|
||||
if (noise == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
PORT_Memcpy(&noise[sizeof rng->V_Data],entropy, entropy_len);
|
||||
}
|
||||
|
||||
rng->V_type = prngReseedType;
|
||||
PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data);
|
||||
prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len,
|
||||
additional_input, additional_input_len);
|
||||
/* clear potential CSP */
|
||||
PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len);
|
||||
rng->V_type = prngCGenerateType;
|
||||
prng_Hash_df(rng->C,sizeof rng->C,rng->V_Data,sizeof rng->V_Data,NULL,0);
|
||||
PRNG_RESET_RESEED_COUNT(rng)
|
||||
|
||||
if (noise != &noiseData[0]) {
|
||||
PORT_Free(noise);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* build some fast inline functions for adding.
|
||||
*/
|
||||
#define PRNG_ADD_CARRY_ONLY(dest, start, cy) \
|
||||
carry = cy; \
|
||||
for (k1=start; carry && k1 >=0 ; k1--) { \
|
||||
carry = !(++dest[k1]); \
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: dest must be an array for the following to work.
|
||||
*/
|
||||
#define PRNG_ADD_BITS(dest, dest_len, add, len) \
|
||||
carry = 0; \
|
||||
for (k1=dest_len -1, k2=len-1; k2 >= 0; --k1, --k2) { \
|
||||
carry += dest[k1]+ add[k2]; \
|
||||
dest[k1] = (PRUint8) carry; \
|
||||
carry >>= 8; \
|
||||
}
|
||||
|
||||
#define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len) \
|
||||
PRNG_ADD_BITS(dest, dest_len, add, len) \
|
||||
PRNG_ADD_CARRY_ONLY(dest, k1, carry)
|
||||
|
||||
/*
|
||||
* This function expands the internal state of the prng to fulfill any number
|
||||
* of bytes we need for this request. We only use this call if we need more
|
||||
* than can be supplied by a single call to SHA256_HashBuf.
|
||||
*
|
||||
* This function is specified in NIST SP 800-90 section 10.1.1.4, Hashgen
|
||||
*/
|
||||
static void
|
||||
prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
|
||||
unsigned int no_of_returned_bytes)
|
||||
{
|
||||
PRUint8 data[VSize(rng)];
|
||||
|
||||
PORT_Memcpy(data, V(rng), VSize(rng));
|
||||
while (no_of_returned_bytes) {
|
||||
SHA256Context ctx;
|
||||
unsigned int len;
|
||||
unsigned int carry;
|
||||
int k1;
|
||||
|
||||
SHA256_Begin(&ctx);
|
||||
SHA256_Update(&ctx, data, sizeof data);
|
||||
SHA256_End(&ctx, returned_bytes, &len, no_of_returned_bytes);
|
||||
returned_bytes += len;
|
||||
no_of_returned_bytes -= len;
|
||||
/* The carry parameter is a bool (increment or not).
|
||||
* This increments data if no_of_returned_bytes is not zero */
|
||||
PRNG_ADD_CARRY_ONLY(data, (sizeof data)- 1, no_of_returned_bytes);
|
||||
}
|
||||
PORT_Memset(data, 0, sizeof data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates new random bytes and advances the internal prng state.
|
||||
* additional bytes are only used in algorithm testing.
|
||||
*
|
||||
* This function is specified in NIST SP 800-90 section 10.1.1.4
|
||||
*/
|
||||
static SECStatus
|
||||
prng_generateNewBytes(RNGContext *rng,
|
||||
PRUint8 *returned_bytes, unsigned int no_of_returned_bytes,
|
||||
const PRUint8 *additional_input,
|
||||
unsigned int additional_input_len)
|
||||
{
|
||||
PRUint8 H[SHA256_LENGTH]; /* both H and w since they
|
||||
* aren't used concurrently */
|
||||
unsigned int carry;
|
||||
int k1, k2;
|
||||
|
||||
if (!rng->isValid) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
/* This code only triggers during tests, normal
|
||||
* prng operation does not use additional_input */
|
||||
if (additional_input){
|
||||
SHA256Context ctx;
|
||||
/* NIST SP 800-90 defines two temporaries in their calculations,
|
||||
* w and H. These temporaries are the same lengths, and used
|
||||
* at different times, so we use the following macro to collapse
|
||||
* them to the same variable, but keeping their unique names for
|
||||
* easy comparison to the spec */
|
||||
#define w H
|
||||
rng->V_type = prngAdditionalDataType;
|
||||
SHA256_Begin(&ctx);
|
||||
SHA256_Update(&ctx, rng->V_Data, sizeof rng->V_Data);
|
||||
SHA256_Update(&ctx, additional_input, additional_input_len);
|
||||
SHA256_End(&ctx, w, NULL, sizeof w);
|
||||
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof w)
|
||||
PORT_Memset(w, 0, sizeof w);
|
||||
#undef w
|
||||
}
|
||||
|
||||
if (no_of_returned_bytes == SHA256_LENGTH) {
|
||||
/* short_cut to hashbuf and save a copy and a clear */
|
||||
SHA256_HashBuf(returned_bytes, V(rng), VSize(rng) );
|
||||
} else {
|
||||
prng_Hashgen(rng, returned_bytes, no_of_returned_bytes);
|
||||
}
|
||||
/* advance our internal state... */
|
||||
rng->V_type = prngGenerateByteType;
|
||||
SHA256_HashBuf(H, rng->V_Data, sizeof rng->V_Data);
|
||||
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), H, sizeof H)
|
||||
PRNG_ADD_BITS(V(rng), VSize(rng), rng->C, sizeof rng->C);
|
||||
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), rng->reseed_counter,
|
||||
sizeof rng->reseed_counter)
|
||||
PRNG_ADD_CARRY_ONLY(rng->reseed_counter,(sizeof rng->reseed_counter)-1, 1);
|
||||
|
||||
/* continuous rng check */
|
||||
if (memcmp(V(rng), rng->oldV, sizeof rng->oldV) == 0) {
|
||||
rng->isValid = PR_FALSE;
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_Memcpy(rng->oldV, V(rng), sizeof rng->oldV);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Use NSPR to prevent RNG_RNGInit from being called from separate
|
||||
* threads, creating a race condition.
|
||||
*/
|
||||
static const PRCallOnceType pristineCallOnce;
|
||||
static PRCallOnceType coRNGInit;
|
||||
static PRStatus rng_init(void)
|
||||
{
|
||||
PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */
|
||||
unsigned int numBytes;
|
||||
if (globalrng == NULL) {
|
||||
/* bytes needs to have enough space to hold
|
||||
* a SHA256 hash value. Blow up at compile time if this isn't true */
|
||||
PR_STATIC_ASSERT(sizeof(bytes) >= SHA256_LENGTH);
|
||||
/* create a new global RNG context */
|
||||
globalrng = &theGlobalRng;
|
||||
PORT_Assert(NULL == globalrng->lock);
|
||||
/* create a lock for it */
|
||||
globalrng->lock = PZ_NewLock(nssILockOther);
|
||||
if (globalrng->lock == NULL) {
|
||||
globalrng = NULL;
|
||||
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/* Try to get some seed data for the RNG */
|
||||
numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes);
|
||||
PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
|
||||
if (numBytes != 0) {
|
||||
/* if this is our first call, instantiate, otherwise reseed
|
||||
* prng_instantiate gets a new clean state, we want to mix
|
||||
* any previous entropy we may have collected */
|
||||
if (V(globalrng)[0] == 0) {
|
||||
prng_instantiate(globalrng, bytes, numBytes);
|
||||
} else {
|
||||
prng_reseed(globalrng, bytes, numBytes, NULL, 0);
|
||||
}
|
||||
memset(bytes, 0, numBytes);
|
||||
} else {
|
||||
PZ_DestroyLock(globalrng->lock);
|
||||
globalrng->lock = NULL;
|
||||
globalrng = NULL;
|
||||
return PR_FAILURE;
|
||||
}
|
||||
/* the RNG is in a valid state */
|
||||
globalrng->isValid = PR_TRUE;
|
||||
|
||||
/* fetch one random value so that we can populate rng->oldV for our
|
||||
* continous random number test. */
|
||||
prng_generateNewBytes(globalrng, bytes, SHA256_LENGTH, NULL, 0);
|
||||
|
||||
/* Fetch more entropy into the PRNG */
|
||||
RNG_SystemInfoForRNG();
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the global RNG context
|
||||
*/
|
||||
static void
|
||||
prng_freeRNGContext(RNGContext *rng)
|
||||
{
|
||||
PRUint8 inputhash[VSize(rng) + (sizeof rng->C)];
|
||||
|
||||
/* destroy context lock */
|
||||
SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock));
|
||||
|
||||
/* zero global RNG context except for C & V to preserve entropy */
|
||||
prng_Hash_df(inputhash, sizeof rng->C, rng->C, sizeof rng->C, NULL, 0);
|
||||
prng_Hash_df(&inputhash[sizeof rng->C], VSize(rng), V(rng), VSize(rng),
|
||||
NULL, 0);
|
||||
memset(rng, 0, sizeof *rng);
|
||||
memcpy(rng->C, inputhash, sizeof rng->C);
|
||||
memcpy(V(rng), &inputhash[sizeof rng->C], VSize(rng));
|
||||
|
||||
memset(inputhash, 0, sizeof inputhash);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize the global RNG context and give it some seed input taken
|
||||
* from the system. This function is thread-safe and will only allow
|
||||
* the global context to be initialized once. The seed input is likely
|
||||
* small, so it is imperative that RNG_RandomUpdate() be called with
|
||||
* additional seed data before the generator is used. A good way to
|
||||
* provide the generator with additional entropy is to call
|
||||
* RNG_SystemInfoForRNG(). Note that C_Initialize() does exactly that.
|
||||
*/
|
||||
SECStatus
|
||||
RNG_RNGInit(void)
|
||||
{
|
||||
/* Allow only one call to initialize the context */
|
||||
PR_CallOnce(&coRNGInit, rng_init);
|
||||
/* Make sure there is a context */
|
||||
return (globalrng != NULL) ? PR_SUCCESS : PR_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Update the global random number generator with more seeding
|
||||
** material.
|
||||
*/
|
||||
SECStatus
|
||||
RNG_RandomUpdate(const void *data, size_t bytes)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
/* Make sure our assumption that size_t is unsigned is true */
|
||||
PR_STATIC_ASSERT(((size_t)-1) > (size_t)1);
|
||||
|
||||
#if defined(NS_PTR_GT_32) || (defined(NSS_USE_64) && !defined(NS_PTR_LE_32))
|
||||
/*
|
||||
* NIST 800-90 requires us to verify our inputs. This value can
|
||||
* come from the application, so we need to make sure it's within the
|
||||
* spec. The spec says it must be less than 2^32 bytes (2^35 bits).
|
||||
* This can only happen if size_t is greater than 32 bits (i.e. on
|
||||
* most 64 bit platforms). The 90% case (perhaps 100% case), size_t
|
||||
* is less than or equal to 32 bits if the platform is not 64 bits, and
|
||||
* greater than 32 bits if it is a 64 bit platform. The corner
|
||||
* cases are handled with explicit defines NS_PTR_GT_32 and NS_PTR_LE_32.
|
||||
*
|
||||
* In general, neither NS_PTR_GT_32 nor NS_PTR_LE_32 will need to be
|
||||
* defined. If you trip over the next two size ASSERTS at compile time,
|
||||
* you will need to define them for your platform.
|
||||
*
|
||||
* if 'sizeof(size_t) > 4' is triggered it means that we were expecting
|
||||
* sizeof(size_t) to be greater than 4, but it wasn't. Setting
|
||||
* NS_PTR_LE_32 will correct that mistake.
|
||||
*
|
||||
* if 'sizeof(size_t) <= 4' is triggered, it means that we were expecting
|
||||
* sizeof(size_t) to be less than or equal to 4, but it wasn't. Setting
|
||||
* NS_PTR_GT_32 will correct that mistake.
|
||||
*/
|
||||
|
||||
PR_STATIC_ASSERT(sizeof(size_t) > 4);
|
||||
|
||||
if (bytes > PRNG_MAX_ADDITIONAL_BYTES) {
|
||||
bytes = PRNG_MAX_ADDITIONAL_BYTES;
|
||||
}
|
||||
#else
|
||||
PR_STATIC_ASSERT(sizeof(size_t) <= 4);
|
||||
#endif
|
||||
|
||||
PZ_Lock(globalrng->lock);
|
||||
/* if we're passed more than our additionalDataCache, simply
|
||||
* call reseed with that data */
|
||||
if (bytes > sizeof (globalrng->additionalDataCache)) {
|
||||
rv = prng_reseed(globalrng, NULL, 0, data, (unsigned int) bytes);
|
||||
/* if we aren't going to fill or overflow the buffer, just cache it */
|
||||
} else if (bytes < ((sizeof globalrng->additionalDataCache)
|
||||
- globalrng->additionalAvail)) {
|
||||
PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail,
|
||||
data, bytes);
|
||||
globalrng->additionalAvail += (PRUint32) bytes;
|
||||
rv = SECSuccess;
|
||||
} else {
|
||||
/* we are going to fill or overflow the buffer. In this case we will
|
||||
* fill the entropy buffer, reseed with it, start a new buffer with the
|
||||
* remainder. We know the remainder will fit in the buffer because
|
||||
* we already handled the case where bytes > the size of the buffer.
|
||||
*/
|
||||
size_t bufRemain = (sizeof globalrng->additionalDataCache)
|
||||
- globalrng->additionalAvail;
|
||||
/* fill the rest of the buffer */
|
||||
if (bufRemain) {
|
||||
PORT_Memcpy(globalrng->additionalDataCache
|
||||
+globalrng->additionalAvail,
|
||||
data, bufRemain);
|
||||
data = ((unsigned char *)data) + bufRemain;
|
||||
bytes -= bufRemain;
|
||||
}
|
||||
/* reseed from buffer */
|
||||
rv = prng_reseed(globalrng, NULL, 0, globalrng->additionalDataCache,
|
||||
sizeof globalrng->additionalDataCache);
|
||||
|
||||
/* copy the rest into the cache */
|
||||
PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
|
||||
globalrng->additionalAvail = (PRUint32) bytes;
|
||||
}
|
||||
|
||||
PZ_Unlock(globalrng->lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate some random bytes, using the global random number generator
|
||||
** object.
|
||||
*/
|
||||
static SECStatus
|
||||
prng_GenerateGlobalRandomBytes(RNGContext *rng,
|
||||
void *dest, size_t len)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
PRUint8 *output = dest;
|
||||
/* check for a valid global RNG context */
|
||||
PORT_Assert(rng != NULL);
|
||||
if (rng == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* FIPS limits the amount of entropy available in a single request */
|
||||
if (len > PRNG_MAX_REQUEST_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* --- LOCKED --- */
|
||||
PZ_Lock(rng->lock);
|
||||
/* Check the amount of seed data in the generator. If not enough,
|
||||
* don't produce any data.
|
||||
*/
|
||||
if (rng->reseed_counter[0] >= RESEED_VALUE) {
|
||||
rv = prng_reseed(rng, NULL, 0, NULL, 0);
|
||||
PZ_Unlock(rng->lock);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
RNG_SystemInfoForRNG();
|
||||
PZ_Lock(rng->lock);
|
||||
}
|
||||
/*
|
||||
* see if we have enough bytes to fulfill the request.
|
||||
*/
|
||||
if (len <= rng->dataAvail) {
|
||||
memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len);
|
||||
memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len);
|
||||
rng->dataAvail -= len;
|
||||
rv = SECSuccess;
|
||||
/* if we are asking for a small number of bytes, cache the rest of
|
||||
* the bytes */
|
||||
} else if (len < sizeof rng->data) {
|
||||
rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data,
|
||||
rng->additionalAvail ? rng->additionalDataCache : NULL,
|
||||
rng->additionalAvail);
|
||||
rng->additionalAvail = 0;
|
||||
if (rv == SECSuccess) {
|
||||
memcpy(output, rng->data, len);
|
||||
memset(rng->data, 0, len);
|
||||
rng->dataAvail = (sizeof rng->data) - len;
|
||||
}
|
||||
/* we are asking for lots of bytes, just ask the generator to pass them */
|
||||
} else {
|
||||
rv = prng_generateNewBytes(rng, output, len,
|
||||
rng->additionalAvail ? rng->additionalDataCache : NULL,
|
||||
rng->additionalAvail);
|
||||
rng->additionalAvail = 0;
|
||||
}
|
||||
PZ_Unlock(rng->lock);
|
||||
/* --- UNLOCKED --- */
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate some random bytes, using the global random number generator
|
||||
** object.
|
||||
*/
|
||||
SECStatus
|
||||
RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
|
||||
{
|
||||
return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
|
||||
}
|
||||
|
||||
void
|
||||
RNG_RNGShutdown(void)
|
||||
{
|
||||
/* check for a valid global RNG context */
|
||||
PORT_Assert(globalrng != NULL);
|
||||
if (globalrng == NULL) {
|
||||
/* Should set a "not initialized" error code. */
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return;
|
||||
}
|
||||
/* clear */
|
||||
prng_freeRNGContext(globalrng);
|
||||
globalrng = NULL;
|
||||
/* reset the callonce struct to allow a new call to RNG_RNGInit() */
|
||||
coRNGInit = pristineCallOnce;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test case interface. used by fips testing and power on self test
|
||||
*/
|
||||
/* make sure the test context is separate from the global context, This
|
||||
* allows us to test the internal random number generator without losing
|
||||
* entropy we may have previously collected. */
|
||||
RNGContext testContext;
|
||||
|
||||
/*
|
||||
* Test vector API. Use NIST SP 800-90 general interface so one of the
|
||||
* other NIST SP 800-90 algorithms may be used in the future.
|
||||
*/
|
||||
SECStatus
|
||||
PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
|
||||
const PRUint8 *nonce, unsigned int nonce_len,
|
||||
const PRUint8 *personal_string, unsigned int ps_len)
|
||||
{
|
||||
int bytes_len = entropy_len + nonce_len + ps_len;
|
||||
PRUint8 *bytes = PORT_Alloc(bytes_len);
|
||||
|
||||
if (bytes == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
/* concatenate the various inputs, internally NSS only instantiates with
|
||||
* a single long string */
|
||||
PORT_Memcpy(bytes, entropy, entropy_len);
|
||||
if (nonce) {
|
||||
PORT_Memcpy(&bytes[entropy_len], nonce, nonce_len);
|
||||
} else {
|
||||
PORT_Assert(nonce_len == 0);
|
||||
}
|
||||
if (personal_string) {
|
||||
PORT_Memcpy(&bytes[entropy_len+nonce_len], personal_string, ps_len);
|
||||
} else {
|
||||
PORT_Assert(ps_len == 0);
|
||||
}
|
||||
prng_instantiate(&testContext, bytes, bytes_len);
|
||||
testContext.isValid = PR_TRUE;
|
||||
PORT_ZFree(bytes, bytes_len);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len,
|
||||
const PRUint8 *additional, unsigned int additional_len)
|
||||
{
|
||||
if (!testContext.isValid) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return prng_reseed(&testContext, entropy, entropy_len, additional,
|
||||
additional_len);
|
||||
|
||||
}
|
||||
|
||||
SECStatus
|
||||
PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
|
||||
const PRUint8 *additional, unsigned int additional_len)
|
||||
{
|
||||
if (!testContext.isValid) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
return prng_generateNewBytes(&testContext, bytes, bytes_len,
|
||||
additional, additional_len);
|
||||
|
||||
}
|
||||
|
||||
SECStatus
|
||||
PRNGTEST_Uninstantiate()
|
||||
{
|
||||
PORT_Memset(&testContext, 0, sizeof testContext);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: dsa.c,v 1.20 2009-03-29 16:51:58 wtc%google.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "prerror.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prinit.h"
|
||||
#include "blapi.h"
|
||||
#include "nssilock.h"
|
||||
#include "secitem.h"
|
||||
#include "blapi.h"
|
||||
#include "mpi.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
/* XXX to be replaced by define in blapit.h */
|
||||
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
#define FIPS_DSA_Q 160
|
||||
#define QSIZE (FIPS_DSA_Q / PR_BITS_PER_BYTE)
|
||||
|
||||
/*
|
||||
* FIPS 186-2 requires result from random output to be reduced mod q when
|
||||
* generating random numbers for DSA.
|
||||
*
|
||||
* Input: w, 2*QSIZE bytes
|
||||
* q, DSA_SUBPRIME_LEN bytes
|
||||
* Output: xj, DSA_SUBPRIME_LEN bytes
|
||||
*/
|
||||
SECStatus
|
||||
FIPS186Change_ReduceModQForDSA(const PRUint8 *w,
|
||||
const PRUint8 *q,
|
||||
PRUint8 *xj)
|
||||
{
|
||||
mp_int W, Q, Xj;
|
||||
mp_err err;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&W) = 0;
|
||||
MP_DIGITS(&Q) = 0;
|
||||
MP_DIGITS(&Xj) = 0;
|
||||
CHECK_MPI_OK( mp_init(&W) );
|
||||
CHECK_MPI_OK( mp_init(&Q) );
|
||||
CHECK_MPI_OK( mp_init(&Xj) );
|
||||
/*
|
||||
* Convert input arguments into MPI integers.
|
||||
*/
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&W, w, 2*QSIZE) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Q, q, DSA_SUBPRIME_LEN) );
|
||||
/*
|
||||
* Algorithm 1 of FIPS 186-2 Change Notice 1, Step 3.3
|
||||
*
|
||||
* xj = (w0 || w1) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mod(&W, &Q, &Xj) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Xj, xj, DSA_SUBPRIME_LEN) );
|
||||
cleanup:
|
||||
mp_clear(&W);
|
||||
mp_clear(&Q);
|
||||
mp_clear(&Xj);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* The core of Algorithm 1 of FIPS 186-2 Change Notice 1.
|
||||
*
|
||||
* We no longer support FIPS 186-2 RNG. This function was exported
|
||||
* for power-up self tests and FIPS tests. Keep this stub, which fails,
|
||||
* to prevent crashes, but also to signal to test code that FIPS 186-2
|
||||
* RNG is no longer supported.
|
||||
*/
|
||||
SECStatus
|
||||
FIPS186Change_GenerateX(PRUint8 *XKEY, const PRUint8 *XSEEDj,
|
||||
PRUint8 *x_j)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specialized RNG for DSA
|
||||
*
|
||||
* As per Algorithm 1 of FIPS 186-2 Change Notice 1, in step 3.3 the value
|
||||
* Xj should be reduced mod q, a 160-bit prime number. Since this parameter
|
||||
* is only meaningful in the context of DSA, the above RNG functions
|
||||
* were implemented without it. They are re-implemented below for use
|
||||
* with DSA.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Generate some random bytes, using the global random number generator
|
||||
** object. In DSA mode, so there is a q.
|
||||
*/
|
||||
static SECStatus
|
||||
dsa_GenerateGlobalRandomBytes(void *dest, size_t len, const PRUint8 *q)
|
||||
{
|
||||
SECStatus rv;
|
||||
PRUint8 w[2*QSIZE];
|
||||
|
||||
PORT_Assert(q && len == DSA_SUBPRIME_LEN);
|
||||
if (len != DSA_SUBPRIME_LEN) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (*q == 0) {
|
||||
++q;
|
||||
}
|
||||
rv = RNG_GenerateGlobalRandomBytes(w, 2*QSIZE);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
FIPS186Change_ReduceModQForDSA(w, q, (PRUint8 *)dest);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void translate_mpi_error(mp_err err)
|
||||
{
|
||||
MP_TO_SEC_ERROR(err);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
||||
const unsigned char *xb)
|
||||
{
|
||||
mp_int p, g;
|
||||
mp_int x, y;
|
||||
mp_err err;
|
||||
PRArenaPool *arena;
|
||||
DSAPrivateKey *key;
|
||||
/* Check args. */
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize an arena for the DSA key. */
|
||||
arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->params.arena = arena;
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
/* Copy over the PQG params */
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime,
|
||||
¶ms->prime) );
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
|
||||
¶ms->subPrime) );
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) );
|
||||
/* Convert stored p, g, and received x into MPI integers. */
|
||||
SECITEM_TO_MPINT(params->prime, &p);
|
||||
SECITEM_TO_MPINT(params->base, &g);
|
||||
OCTETS_TO_MPINT(xb, &x, DSA_SUBPRIME_LEN);
|
||||
/* Store x in private key */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
|
||||
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
|
||||
/* Compute public key y = g**x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
|
||||
/* Store y in public key */
|
||||
MPINT_TO_SECITEM(&y, &key->publicValue, arena);
|
||||
*privKey = key;
|
||||
key = NULL;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&y);
|
||||
if (key)
|
||||
PORT_FreeArena(key->params.arena, PR_TRUE);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
** "params" is a pointer to the PQG parameters for the domain
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned char seed[DSA_SUBPRIME_LEN];
|
||||
int retries = 10;
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
do {
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (dsa_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
|
||||
params->subPrime.data))
|
||||
return SECFailure;
|
||||
/* Disallow values of 0 and 1 for x. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN-1; i++) {
|
||||
if (seed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good && seed[i] > 1) {
|
||||
good = PR_TRUE;
|
||||
}
|
||||
} while (!good && --retries > 0);
|
||||
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Generate a new DSA key using random seed. */
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
|
||||
SECStatus
|
||||
DSA_NewKeyFromSeed(const PQGParams *params,
|
||||
const unsigned char *seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
|
||||
const unsigned char *kb)
|
||||
{
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int x, k; /* private key & pseudo-random integer */
|
||||
mp_int r, s; /* tuple (r, s) is signature) */
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len < DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&s) );
|
||||
/*
|
||||
** Convert stored PQG and private key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->privateValue, &x);
|
||||
OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN);
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 1
|
||||
**
|
||||
** r = (g**k mod p) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
|
||||
CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 2
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + x*r)) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
|
||||
CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
|
||||
CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
|
||||
CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
|
||||
/*
|
||||
** verify r != 0 and s != 0
|
||||
** mentioned as optional in FIPS 186-1.
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
** Step 4
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = MP_OKAY;
|
||||
signature->len = DSA_SIGNATURE_LEN;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 40 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
** On output, signature->len == size of signature in buffer.
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv;
|
||||
int retries = 10;
|
||||
unsigned char kSeed[DSA_SUBPRIME_LEN];
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
PORT_SetError(0);
|
||||
do {
|
||||
rv = dsa_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
|
||||
key->params.subPrime.data);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
/* Disallow a value of 0 for k. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN; i++) {
|
||||
if (kSeed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
continue;
|
||||
}
|
||||
rv = dsa_SignDigest(key, signature, digest, kSeed);
|
||||
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
|
||||
--retries > 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes. */
|
||||
SECStatus
|
||||
DSA_SignDigestWithSeed(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_SignDigest(key, signature, digest, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int u1, u2, v, w; /* intermediate values used in verification */
|
||||
mp_int y; /* public key */
|
||||
mp_err err;
|
||||
SECStatus verified = SECFailure;
|
||||
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r_) );
|
||||
CHECK_MPI_OK( mp_init(&s_) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&v) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
/*
|
||||
** Convert stored PQG and public key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->publicValue, &y);
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
|
||||
OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
|
||||
/*
|
||||
** Verify that 0 < r' < q and 0 < s' < q
|
||||
*/
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
|
||||
/* err is zero here. */
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
goto cleanup; /* will return verified == SECFailure */
|
||||
}
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 1
|
||||
**
|
||||
** w = (s')**-1 mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 2
|
||||
**
|
||||
** u1 = ((SHA1(M')) * w) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 3
|
||||
**
|
||||
** u2 = ((r') * w) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 4
|
||||
**
|
||||
** v = ((g**u1 * y**u2) mod p) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
|
||||
CHECK_MPI_OK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
|
||||
CHECK_MPI_OK( mp_mod(&v, &q, &v) ); /* v = v mod q */
|
||||
/*
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
verified = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
verified = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&w);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
}
|
||||
return verified;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ec_h_
|
||||
#define __ec_h_
|
||||
|
||||
#define EC_DEBUG 0
|
||||
#define EC_POINT_FORM_COMPRESSED_Y0 0x02
|
||||
#define EC_POINT_FORM_COMPRESSED_Y1 0x03
|
||||
#define EC_POINT_FORM_UNCOMPRESSED 0x04
|
||||
#define EC_POINT_FORM_HYBRID_Y0 0x06
|
||||
#define EC_POINT_FORM_HYBRID_Y1 0x07
|
||||
|
||||
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
|
||||
#define SECG_CURVE_OID_TOTAL_LEN 7
|
||||
|
||||
#endif /* __ec_h_ */
|
||||
@@ -1,230 +0,0 @@
|
||||
#
|
||||
# Makefile for elliptic curve library
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the elliptic curve math library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Sun Microsystems, Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2003
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Douglas Stebila <douglas@stebila.ca>
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
# Netscape Communications Corporation
|
||||
# Richard C. Swift (swift@netscape.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
#PERL=perl
|
||||
|
||||
include ../mpi/target.mk
|
||||
|
||||
##
|
||||
## Define platform-dependent variables for use of floating-point code.
|
||||
##
|
||||
ifeq ($(TARGET),v9SOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),v8plusSOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),v8SOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),x86LINUX)
|
||||
ECL_USE_FP=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
##
|
||||
## Add to definition of CFLAGS depending on use of floating-point code.
|
||||
##
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
CFLAGS+= -DECL_USE_FP
|
||||
endif
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=-L../mpi -lmpi -lm#-lmalloc#-lefence
|
||||
|
||||
##
|
||||
## Define INCLUDES to include any include directories you need to
|
||||
## compile with.
|
||||
##
|
||||
INCLUDES=-I../mpi
|
||||
CFLAGS+= $(INCLUDES) $(XCFLAGS)
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## Define LIBOBJS to be the object files that will be created during
|
||||
## the build process.
|
||||
##
|
||||
LIBOBJS = ecl.o ecl_curve.o ecl_mult.o ecl_gf.o \
|
||||
ec2_aff.o ec2_mont.o ec2_proj.o \
|
||||
ec2_163.o ec2_193.o ec2_233.o \
|
||||
ecp_aff.o ecp_jac.o ecp_mont.o \
|
||||
ec_naf.o ecp_jm.o \
|
||||
ecp_192.o ecp_224.o ecp_256.o ecp_384.o ecp_521.o
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
LIBOBJS+= ecp_fp160.o ecp_fp192.o ecp_fp224.o ecp_fp.o
|
||||
endif
|
||||
|
||||
## The headers contained in this library.
|
||||
LIBHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h
|
||||
APPHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h
|
||||
ifeq ($(ECL_GFP_ASSEMBLY_FP),1)
|
||||
LIBHDRS += ecp_fp.h
|
||||
APPHDRS += ecp_fp.h
|
||||
endif
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "libecl.a - elliptic curve library"
|
||||
@ echo "tests - build command line tests"
|
||||
@ echo "test - run command line tests"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .o .i
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
ecl.o: ecl.c $(LIBHDRS)
|
||||
ecl_curve.o: ecl_curve.c $(LIBHDRS)
|
||||
ecl_mult.o: ecl_mult.c $(LIBHDRS)
|
||||
ecl_gf.o: ecl_gf.c $(LIBHDRS)
|
||||
ec2_aff.o: ec2_aff.c $(LIBHDRS)
|
||||
ec2_mont.o: ec2_mont.c $(LIBHDRS)
|
||||
ec2_proj.o: ec2_proj.c $(LIBHDRS)
|
||||
ec2_163.o: ec2_163.c $(LIBHDRS)
|
||||
ec2_193.o: ec2_193.c $(LIBHDRS)
|
||||
ec2_233.o: ec2_233.c $(LIBHDRS)
|
||||
ecp_aff.o: ecp_aff.c $(LIBHDRS)
|
||||
ecp_jac.o: ecp_jac.c $(LIBHDRS)
|
||||
ecp_jm.o: ecp_jm.c $(LIBHDRS)
|
||||
ecp_mont.o: ecp_mont.c $(LIBHDRS)
|
||||
ecp_192.o: ecp_192.c $(LIBHDRS)
|
||||
ecp_224.o: ecp_224.c $(LIBHDRS)
|
||||
ecp_256.o: ecp_256.c $(LIBHDRS)
|
||||
ecp_384.o: ecp_384.c $(LIBHDRS)
|
||||
ecp_521.o: ecp_521.c $(LIBHDRS)
|
||||
ecp_fp.o: ecp_fp.c $(LIBHDRS)
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
ecp_fp160.o: ecp_fp160.c ecp_fpinc.c $(LIBHDRS)
|
||||
ecp_fp192.o: ecp_fp192.c ecp_fpinc.c $(LIBHDRS)
|
||||
ecp_fp224.o: ecp_fp224.c ecp_fpinc.c $(LIBHDRS)
|
||||
endif
|
||||
|
||||
libecl.a: $(LIBOBJS)
|
||||
ar -cvr libecl.a $(LIBOBJS)
|
||||
$(RANLIB) libecl.a
|
||||
|
||||
lib libs: libecl.a
|
||||
|
||||
ecl.i: ecl.h
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
ECLTESTOBJS = ec2_test.o ecp_test.o ec_naft.o
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
ECLTESTOBJS+= ecp_fpt.o
|
||||
endif
|
||||
ECLTESTS = $(ECLTESTOBJS:.o=)
|
||||
|
||||
$(ECLTESTOBJS): %.o: tests/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDES)
|
||||
|
||||
$(ECLTESTS): %: %.o libecl.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
tests: ec2_test ecp_test ec_naft ecp_fpt
|
||||
else
|
||||
tests: ec2_test ecp_test ec_naft
|
||||
endif
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
test: tests
|
||||
./ecp_test
|
||||
./ec2_test
|
||||
./ec_naft
|
||||
./ecp_fpt
|
||||
else
|
||||
test: tests
|
||||
./ecp_test
|
||||
./ec_naft
|
||||
./ec2_test
|
||||
endif
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.i
|
||||
rm -f core
|
||||
rm -f *~ .*~
|
||||
rm -f $(ECLTESTS)
|
||||
|
||||
clobber: clean
|
||||
|
||||
# END
|
||||
@@ -1,330 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the elliptic curve math library.
|
||||
|
||||
The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
Sun Microsystems, Inc. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Stephen Fung <fungstep@hotmail.com> and
|
||||
Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
The ECL exposes routines for constructing and converting curve
|
||||
parameters for internal use.
|
||||
|
||||
|
||||
HEADER FILES
|
||||
============
|
||||
|
||||
ecl-exp.h - Exports data structures and curve names. For use by code
|
||||
that does not have access to mp_ints.
|
||||
|
||||
ecl-curve.h - Provides hex encodings (in the form of ECCurveParams
|
||||
structs) of standardizes elliptic curve domain parameters and mappings
|
||||
from ECCurveName to ECCurveParams. For use by code that does not have
|
||||
access to mp_ints.
|
||||
|
||||
ecl.h - Interface to constructors for curve parameters and group object,
|
||||
and point multiplication operations. Used by higher level algorithms
|
||||
(like ECDH and ECDSA) to actually perform elliptic curve cryptography.
|
||||
|
||||
ecl-priv.h - Data structures and functions for internal use within the
|
||||
library.
|
||||
|
||||
ec2.h - Internal header file that contains all functions for point
|
||||
arithmetic over binary polynomial fields.
|
||||
|
||||
ecp.h - Internal header file that contains all functions for point
|
||||
arithmetic over prime fields.
|
||||
|
||||
DATA STRUCTURES AND TYPES
|
||||
=========================
|
||||
|
||||
ECCurveName (from ecl-exp.h) - Opaque name for standardized elliptic
|
||||
curve domain parameters.
|
||||
|
||||
ECCurveParams (from ecl-exp.h) - Provides hexadecimal encoding
|
||||
of elliptic curve domain parameters. Can be generated by a user
|
||||
and passed to ECGroup_fromHex or can be generated from a name by
|
||||
EC_GetNamedCurveParams. ecl-curve.h contains ECCurveParams structs for
|
||||
the standardized curves defined by ECCurveName.
|
||||
|
||||
ECGroup (from ecl.h and ecl-priv.h) - Opaque data structure that
|
||||
represents a group of elliptic curve points for a particular set of
|
||||
elliptic curve domain parameters. Contains all domain parameters (curve
|
||||
a and b, field, base point) as well as pointers to the functions that
|
||||
should be used for point arithmetic and the underlying field GFMethod.
|
||||
Generated by either ECGroup_fromHex or ECGroup_fromName.
|
||||
|
||||
GFMethod (from ecl-priv.h) - Represents a field underlying a set of
|
||||
elliptic curve domain parameters. Contains the irreducible that defines
|
||||
the field (either the prime or the binary polynomial) as well as
|
||||
pointers to the functions that should be used for field arithmetic.
|
||||
|
||||
ARITHMETIC FUNCTIONS
|
||||
====================
|
||||
|
||||
Higher-level algorithms (like ECDH and ECDSA) should call ECPoint_mul
|
||||
or ECPoints_mul (from ecl.h) to do point arithmetic. These functions
|
||||
will choose which underlying algorithms to use, based on the ECGroup
|
||||
structure.
|
||||
|
||||
Point Multiplication
|
||||
--------------------
|
||||
|
||||
ecl_mult.c provides the ECPoints_mul and ECPoint_mul wrappers.
|
||||
It also provides two implementations for the pts_mul operation -
|
||||
ec_pts_mul_basic (which computes kP, lQ, and then adds kP + lQ) and
|
||||
ec_pts_mul_simul_w2 (which does a simultaneous point multiplication
|
||||
using a table with window size 2*2).
|
||||
|
||||
ec_naf.c provides an implementation of an algorithm to calculate a
|
||||
non-adjacent form of a scalar, minimizing the number of point
|
||||
additions that need to be done in a point multiplication.
|
||||
|
||||
Point Arithmetic over Prime Fields
|
||||
----------------------------------
|
||||
|
||||
ecp_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ecp_jac.c provides point arithmetic using Jacobian projective
|
||||
coordinates and mixed Jacobian-affine coordinates. (Jacobian projective
|
||||
coordinates represent a point (x, y) as (X, Y, Z), where x=X/Z^2,
|
||||
y=Y/Z^3).
|
||||
|
||||
ecp_jm.c provides point arithmetic using Modified Jacobian
|
||||
coordinates and mixed Modified_Jacobian-affine coordinates.
|
||||
(Modified Jacobian coordinates represent a point (x, y)
|
||||
as (X, Y, Z, a*Z^4), where x=X/Z^2, y=Y/Z^3, and a is
|
||||
the linear coefficient in the curve defining equation).
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized field arithmetic.
|
||||
|
||||
Point Arithmetic over Binary Polynomial Fields
|
||||
----------------------------------------------
|
||||
|
||||
ec2_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ec2_proj.c provides point arithmetic using projective coordinates.
|
||||
(Projective coordinates represent a point (x, y) as (X, Y, Z), where
|
||||
x=X/Z, y=Y/Z^2).
|
||||
|
||||
ec2_mont.c provides point multiplication using Montgomery projective
|
||||
coordinates.
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
|
||||
|
||||
Field Arithmetic
|
||||
----------------
|
||||
|
||||
ecl_gf.c provides constructors for field objects (GFMethod) with the
|
||||
functions GFMethod_cons*. It also provides wrappers around the basic
|
||||
field operations.
|
||||
|
||||
Prime Field Arithmetic
|
||||
----------------------
|
||||
|
||||
The mpi library provides the basic prime field arithmetic.
|
||||
|
||||
ecp_mont.c provides wrappers around the Montgomery multiplication
|
||||
functions from the mpi library and adds encoding and decoding functions.
|
||||
It also provides the function to construct a GFMethod object using
|
||||
Montgomery multiplication.
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized modular reduction for the
|
||||
fields defined by nistp192 and nistp224 primes.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Binary Polynomial Field Arithmetic
|
||||
----------------------------------
|
||||
|
||||
../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
|
||||
including addition, multiplication, squaring, mod, and division, as well
|
||||
as conversion ob polynomial representations between bitstring and int[].
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
|
||||
and sqr operations.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Field Encoding
|
||||
--------------
|
||||
|
||||
By default, field elements are encoded in their basic form. It is
|
||||
possible to use an alternative encoding, however. For example, it is
|
||||
possible to Montgomery representation of prime field elements and
|
||||
take advantage of the fast modular multiplication that Montgomery
|
||||
representation provides. The process of converting from basic form to
|
||||
Montgomery representation is called field encoding, and the opposite
|
||||
process would be field decoding. All internal point operations assume
|
||||
that the operands are field encoded as appropriate. By rewiring the
|
||||
underlying field arithmetic to perform operations on these encoded
|
||||
values, the same overlying point arithmetic operations can be used
|
||||
regardless of field representation.
|
||||
|
||||
ALGORITHM WIRING
|
||||
================
|
||||
|
||||
The EC library allows point and field arithmetic algorithms to be
|
||||
substituted ("wired-in") on a fine-grained basis. This allows for
|
||||
generic algorithms and algorithms that are optimized for a particular
|
||||
curve, field, or architecture, to coexist and to be automatically
|
||||
selected at runtime.
|
||||
|
||||
Wiring Mechanism
|
||||
----------------
|
||||
|
||||
The ECGroup and GFMethod structure contain pointers to the point and
|
||||
field arithmetic functions, respectively, that are to be used in
|
||||
operations.
|
||||
|
||||
The selection of algorithms to use is handled in the function
|
||||
ecgroup_fromNameAndHex in ecl.c.
|
||||
|
||||
Default Wiring
|
||||
--------------
|
||||
|
||||
Curves over prime fields by default use montgomery field arithmetic,
|
||||
point multiplication using 5-bit window non-adjacent-form with
|
||||
Modified Jacobian coordinates, and 2*2-bit simultaneous point
|
||||
multiplication using Jacobian coordinates.
|
||||
(Wiring in function ECGroup_consGFp_mont in ecl.c.)
|
||||
|
||||
Curves over prime fields that have optimized modular reduction (i.e.,
|
||||
secp160r1, nistp192, and nistp224) do not use Montgomery field
|
||||
arithmetic. Instead, they use basic field arithmetic with their
|
||||
optimized reduction (as in ecp_192.c and ecp_224.c). They
|
||||
use the same point multiplication and simultaneous point multiplication
|
||||
algorithms as other curves over prime fields.
|
||||
|
||||
Curves over binary polynomial fields by default use generic field
|
||||
arithmetic with montgomery point multiplication and basic kP + lQ
|
||||
computation (multiply, multiply, and add). (Wiring in function
|
||||
ECGroup_cons_GF2m in ecl.c.)
|
||||
|
||||
Curves over binary polynomial fields that have optimized field
|
||||
arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
|
||||
field arithmetic. They use the same point multiplication and
|
||||
simultaneous point multiplication algorithms as other curves over binary
|
||||
fields.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
We provide an example for plugging in an optimized implementation for
|
||||
the Koblitz curve nistk163.
|
||||
|
||||
Suppose the file ec2_k163.c contains the optimized implementation. In
|
||||
particular it contains a point multiplication function:
|
||||
|
||||
mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
Since only a pt_mul function is provided, the generic pt_add function
|
||||
will be used.
|
||||
|
||||
There are two options for handling the optimized field arithmetic used
|
||||
by the ..._pt_mul function. Say the optimized field arithmetic includes
|
||||
the following functions:
|
||||
|
||||
mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
|
||||
First, the optimized field arithmetic could simply be called directly
|
||||
by the ..._pt_mul function. This would be accomplished by changing
|
||||
the ecgroup_fromNameAndHex function in ecl.c to include the following
|
||||
statements:
|
||||
|
||||
if (name == ECCurve_NIST_K163) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
|
||||
&geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK( ec_group_set_nistk163(group) );
|
||||
}
|
||||
|
||||
and including in ec2_k163.c the following function:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
As a result, ec_GF2m_pt_add and similar functions would use the
|
||||
basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
|
||||
ec_GF2m_sqr, and ec_GF2m_div.
|
||||
|
||||
Alternatively, the optimized field arithmetic could be wired into the
|
||||
group's GFMethod. This would be accomplished by putting the following
|
||||
function in ec2_k163.c:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->meth->field_add = &ec_GF2m_nistk163_add;
|
||||
group->meth->field_mul = &ec_GF2m_nistk163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
|
||||
group->meth->field_div = &ec_GF2m_nistk163_div;
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
For an example of functions that use special field encodings, take a
|
||||
look at ecp_mont.c.
|
||||
|
||||
TESTING
|
||||
=======
|
||||
|
||||
The ecl/tests directory contains a collection of standalone tests that
|
||||
verify the correctness of the elliptic curve library.
|
||||
|
||||
Both ecp_test and ec2_test take the following arguments:
|
||||
|
||||
--print Print out results of each point arithmetic test.
|
||||
--time Benchmark point operations and print results.
|
||||
|
||||
The set of curves over which ecp_test and ec2_test run is coded into the
|
||||
program, but can be changed by editing the source files.
|
||||
|
||||
BUILDING
|
||||
========
|
||||
|
||||
The ecl can be built as a standalone library, separate from NSS,
|
||||
dependent only on the mpi library. To build the library:
|
||||
|
||||
> cd ../mpi
|
||||
> make libs
|
||||
> cd ../ecl
|
||||
> make libs
|
||||
> make tests # to build test files
|
||||
> make test # to run automated tests
|
||||
@@ -1,317 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the elliptic curve math library.
|
||||
|
||||
The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
Sun Microsystems, Inc. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Stephen Fung <fungstep@hotmail.com> and
|
||||
Nils Gura <nils.gura@sun.com>, Sun Microsystems Laboratories
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
The ECL exposes routines for constructing and converting curve
|
||||
parameters for internal use.
|
||||
|
||||
The floating point code of the ECL provides algorithms for performing
|
||||
elliptic-curve point multiplications in floating point.
|
||||
|
||||
The point multiplication algorithms perform calculations almost
|
||||
exclusively in floating point for efficiency, but have the same
|
||||
(integer) interface as the ECL for compatibility and to be easily
|
||||
wired-in to the ECL. Please see README file (not this README.FP file)
|
||||
for information on wiring-in.
|
||||
|
||||
This has been implemented for 3 curves as specified in [1]:
|
||||
secp160r1
|
||||
secp192r1
|
||||
secp224r1
|
||||
|
||||
RATIONALE
|
||||
=========
|
||||
Calculations are done in the floating-point unit (FPU) since it
|
||||
gives better performance on the UltraSPARC III chips. This is
|
||||
because the FPU allows for faster multiplication than the integer unit.
|
||||
The integer unit has a longer multiplication instruction latency, and
|
||||
does not allow full pipelining, as described in [2].
|
||||
Since performance is an important selling feature of Elliptic Curve
|
||||
Cryptography (ECC), this implementation was created.
|
||||
|
||||
DATA REPRESENTATION
|
||||
===================
|
||||
Data is primarily represented in an array of double-precision floating
|
||||
point numbers. Generally, each array element has 24 bits of precision
|
||||
(i.e. be x * 2^y, where x is an integer of at most 24 bits, y some positive
|
||||
integer), although the actual implementation details are more complicated.
|
||||
|
||||
e.g. a way to store an 80 bit number might be:
|
||||
double p[4] = { 632613 * 2^0, 329841 * 2^24, 9961 * 2^48, 51 * 2^64 };
|
||||
See section ARITHMETIC OPERATIONS for more details.
|
||||
|
||||
This implementation assumes that the floating-point unit rounding mode
|
||||
is round-to-even as specified in IEEE 754
|
||||
(as opposed to chopping, rounding up, or rounding down).
|
||||
When subtracting integers represented as arrays of floating point
|
||||
numbers, some coefficients (array elements) may become negative.
|
||||
This effectively gives an extra bit of precision that is important
|
||||
for correctness in some cases.
|
||||
|
||||
The described number presentation limits the size of integers to 1023 bits.
|
||||
This is due to an upper bound of 1024 for the exponent of a double precision
|
||||
floating point number as specified in IEEE-754.
|
||||
However, this is acceptable for ECC key sizes of the foreseeable future.
|
||||
|
||||
DATA STRUCTURES
|
||||
===============
|
||||
For more information on coordinate representations, see [3].
|
||||
|
||||
ecfp_aff_pt
|
||||
-----------
|
||||
Affine EC Point Representation. This is the basic
|
||||
representation (x, y) of an elliptic curve point.
|
||||
|
||||
ecfp_jac_pt
|
||||
-----------
|
||||
Jacobian EC Point. This stores a point as (X, Y, Z), where
|
||||
the affine point corresponds to (X/Z^2, Y/Z^3). This allows
|
||||
for fewer inversions in calculations.
|
||||
|
||||
ecfp_chud_pt
|
||||
------------
|
||||
Chudnovsky Jacobian Point. This representation stores a point
|
||||
as (X, Y, Z, Z^2, Z^3), the same as a Jacobian representation
|
||||
but also storing Z^2 and Z^3 for faster point additions.
|
||||
|
||||
ecfp_jm_pt
|
||||
----------
|
||||
Modified Jacobian Point. This representation stores a point
|
||||
as (X, Y, Z, a*Z^4), the same as Jacobian representation but
|
||||
also storing a*Z^4 for faster point doublings. Here "a" represents
|
||||
the linear coefficient of x defining the curve.
|
||||
|
||||
EC_group_fp
|
||||
-----------
|
||||
Stores information on the elliptic curve group for floating
|
||||
point calculations. Contains curve specific information, as
|
||||
well as function pointers to routines, allowing different
|
||||
optimizations to be easily wired in.
|
||||
This should be made accessible from an ECGroup for the floating
|
||||
point implementations of point multiplication.
|
||||
|
||||
POINT MULTIPLICATION ALGORITHMS
|
||||
===============================
|
||||
Elliptic Curve Point multiplication can be done at a higher level orthogonal
|
||||
to the implementation of point additions and point doublings. There
|
||||
are a variety of algorithms that can be used.
|
||||
|
||||
The following algorithms have been implemented:
|
||||
|
||||
4-bit Window (Jacobian Coordinates)
|
||||
Double & Add (Jacobian & Affine Coordinates)
|
||||
5-bit Non-Adjacent Form (Modified Jacobian & Chudnovsky Jacobian)
|
||||
|
||||
Currently, the fastest algorithm for multiplying a generic point
|
||||
is the 5-bit Non-Adjacent Form.
|
||||
|
||||
See comments in ecp_fp.c for more details and references.
|
||||
|
||||
SOURCE / HEADER FILES
|
||||
=====================
|
||||
|
||||
ecp_fp.c
|
||||
--------
|
||||
Main source file for floating point calculations. Contains routines
|
||||
to convert from floating-point to integer (mp_int format), point
|
||||
multiplication algorithms, and several other routines.
|
||||
|
||||
ecp_fp.h
|
||||
--------
|
||||
Main header file. Contains most constants used and function prototypes.
|
||||
|
||||
ecp_fp[160, 192, 224].c
|
||||
-----------------------
|
||||
Source files for specific curves. Contains curve specific code such
|
||||
as specialized reduction based on the field defining prime. Contains
|
||||
code wiring-in different algorithms and optimizations.
|
||||
|
||||
ecp_fpinc.c
|
||||
-----------
|
||||
Source file that is included by ecp_fp[160, 192, 224].c. This generates
|
||||
functions with different preprocessor-defined names and loop iterations,
|
||||
allowing for static linking and strong compiler optimizations without
|
||||
code duplication.
|
||||
|
||||
TESTING
|
||||
=======
|
||||
The test suite can be found in ecl/tests/ecp_fpt. This tests and gets
|
||||
timings of the different algorithms for the curves implemented.
|
||||
|
||||
ARITHMETIC OPERATIONS
|
||||
---------------------
|
||||
The primary operations in ECC over the prime fields are modular arithmetic:
|
||||
i.e. n * m (mod p) and n + m (mod p). In this implementation, multiplication,
|
||||
addition, and reduction are implemented as separate functions. This
|
||||
enables computation of formulae with fewer reductions, e.g.
|
||||
(a * b) + (c * d) (mod p) rather than:
|
||||
((a * b) (mod p)) + ((c * d) (mod p)) (mod p)
|
||||
This takes advantage of the fact that the double precision mantissa in
|
||||
floating point can hold numbers up to 2^53, i.e. it has some leeway to
|
||||
store larger intermediate numbers. See further detail in the section on
|
||||
FLOATING POINT PRECISION.
|
||||
|
||||
Multiplication
|
||||
--------------
|
||||
Multiplication is implemented in a standard polynomial multiplication
|
||||
fashion. The terms in opposite factors are pairwise multiplied and
|
||||
added together appropriately. Note that the result requires twice
|
||||
as many doubles for storage, as the bit size of the product is twice
|
||||
that of the multiplicands.
|
||||
e.g. suppose we have double n[3], m[3], r[6], and want to calculate r = n * m
|
||||
r[0] = n[0] * m[0]
|
||||
r[1] = n[0] * m[1] + n[1] * m[0]
|
||||
r[2] = n[0] * m[2] + n[1] * m[1] + n[2] * m[0]
|
||||
r[3] = n[1] * m[2] + n[2] * m[1]
|
||||
r[4] = n[2] * m[2]
|
||||
r[5] = 0 (This is used later to hold spillover from r[4], see tidying in
|
||||
the reduction section.)
|
||||
|
||||
Addition
|
||||
--------
|
||||
Addition is done term by term. The only caveat is to be careful with
|
||||
the number of terms that need to be added. When adding results of
|
||||
multiplication (before reduction), twice as many terms need to be added
|
||||
together. This is done in the addLong function.
|
||||
e.g. for double n[4], m[4], r[4]: r = n + m
|
||||
r[0] = n[0] + m[0]
|
||||
r[1] = n[1] + m[1]
|
||||
r[2] = n[2] + m[2]
|
||||
r[3] = n[3] + m[3]
|
||||
|
||||
Modular Reduction
|
||||
-----------------
|
||||
For the curves implemented, reduction is possible by fast reduction
|
||||
for Generalized Mersenne Primes, as described in [4]. For the
|
||||
floating point implementation, a significant step of the reduction
|
||||
process is tidying: that is, the propagation of carry bits from
|
||||
low-order to high-order coefficients to reduce the precision of each
|
||||
coefficient to 24 bits.
|
||||
This is done by adding and then subtracting
|
||||
ecfp_alpha, a large floating point number that induces precision roundoff.
|
||||
See [5] for more details on tidying using floating point arithmetic.
|
||||
e.g. suppose we have r = 961838 * 2^24 + 519308
|
||||
then if we set alpha = 3 * 2^51 * 2^24,
|
||||
FP(FP(r + alpha) - alpha) = 961838 * 2^24, because the precision for
|
||||
the intermediate results is limited. Our values of alpha are chosen
|
||||
to truncate to a desired number of bits.
|
||||
|
||||
The reduction is then performed as in [4], adding multiples of prime p.
|
||||
e.g. suppose we are working over a polynomial of 10^2. Take the number
|
||||
2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95, stored in 5 elements
|
||||
for coefficients of 10^0, 10^2, ..., 10^8.
|
||||
We wish to reduce modulo p = 10^6 - 2 * 10^4 + 1
|
||||
We can subtract off from the higher terms
|
||||
(2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95) - (2 * 10^2) * (10^6 - 2 * 10^4 + 1)
|
||||
= 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95
|
||||
= 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95 - (15) * (10^6 - 2 * 10^4 + 1)
|
||||
= 83 * 10^4 + 21 * 10^2 + 80
|
||||
|
||||
Integrated Example
|
||||
------------------
|
||||
This example shows how multiplication, addition, tidying, and reduction
|
||||
work together in our modular arithmetic. This is simplified from the
|
||||
actual implementation, but should convey the main concepts.
|
||||
Working over polynomials of 10^2 and with p as in the prior example,
|
||||
Let a = 16 * 10^4 + 53 * 10^2 + 33
|
||||
let b = 81 * 10^4 + 31 * 10^2 + 49
|
||||
let c = 22 * 10^4 + 0 * 10^2 + 95
|
||||
And suppose we want to compute a * b + c mod p.
|
||||
We first do a multiplication: then a * b =
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5100 * 10^4 + 3620 * 10^2 + 1617
|
||||
Then we add in c before doing reduction, allowing us to get a * b + c =
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
We then perform a tidying on the upper half of the terms:
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6
|
||||
0 * 10^10 + (1296 + 47) * 10^8 + 89 * 10^6
|
||||
0 * 10^10 + 1343 * 10^8 + 89 * 10^6
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6
|
||||
which then gives us
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
we then reduce modulo p similar to the reduction example above:
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
- (13 * 10^4 * p)
|
||||
69 * 10^8 + 89 * 10^6 + 5109 * 10^4 + 3620 * 10^2 + 1712
|
||||
- (69 * 10^2 * p)
|
||||
227 * 10^6 + 5109 * 10^4 + 3551 * 10^2 + 1712
|
||||
- (227 * p)
|
||||
5563 * 10^4 + 3551 * 10^2 + 1485
|
||||
finally, we do tidying to get the precision of each term down to 2 digits
|
||||
5563 * 10^4 + 3565 * 10^2 + 85
|
||||
5598 * 10^4 + 65 * 10^2 + 85
|
||||
55 * 10^6 + 98 * 10^4 + 65 * 10^2 + 85
|
||||
and perform another reduction step
|
||||
- (55 * p)
|
||||
208 * 10^4 + 65 * 10^2 + 30
|
||||
There may be a small number of further reductions that could be done at
|
||||
this point, but this is typically done only at the end when converting
|
||||
from floating point to an integer unit representation.
|
||||
|
||||
FLOATING POINT PRECISION
|
||||
========================
|
||||
This section discusses the precision of floating point numbers, which
|
||||
one writing new formulae or a larger bit size should be aware of. The
|
||||
danger is that an intermediate result may be required to store a
|
||||
mantissa larger than 53 bits, which would cause error by rounding off.
|
||||
|
||||
Note that the tidying with IEEE rounding mode set to round-to-even
|
||||
allows negative numbers, which actually reduces the size of the double
|
||||
mantissa to 23 bits - since it rounds the mantissa to the nearest number
|
||||
modulo 2^24, i.e. roughly between -2^23 and 2^23.
|
||||
A multiplication increases the bit size to 2^46 * n, where n is the number
|
||||
of doubles to store a number. For the 224 bit curve, n = 10. This gives
|
||||
doubles of size 5 * 2^47. Adding two of these doubles gives a result
|
||||
of size 5 * 2^48, which is less than 2^53, so this is safe.
|
||||
Similar analysis can be done for other formulae to ensure numbers remain
|
||||
below 2^53.
|
||||
|
||||
Extended-Precision Floating Point
|
||||
---------------------------------
|
||||
Some platforms, notably x86 Linux, may use an extended-precision floating
|
||||
point representation that has a 64-bit mantissa. [6] Although this
|
||||
implementation is optimized for the IEEE standard 53-bit mantissa,
|
||||
it should work with the 64-bit mantissa. A check is done at run-time
|
||||
in the function ec_set_fp_precision that detects if the precision is
|
||||
greater than 53 bits, and runs code for the 64-bit mantissa accordingly.
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
[1] Certicom Corp., "SEC 2: Recommended Elliptic Curve Domain Parameters", Sept. 20, 2000. www.secg.org
|
||||
[2] Sun Microsystems Inc. UltraSPARC III Cu User's Manual, Version 1.0, May 2002, Table 4.4
|
||||
[3] H. Cohen, A. Miyaji, and T. Ono, "Efficient Elliptic Curve Exponentiation Using Mixed Coordinates".
|
||||
[4] Henk C.A. van Tilborg, Generalized Mersenne Prime. http://www.win.tue.nl/~henkvt/GenMersenne.pdf
|
||||
[5] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2.
|
||||
[6] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2 Notes.
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ec2_h_
|
||||
#define __ec2_h_
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses Montgomery projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). */
|
||||
mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* __ec2_h_ */
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 6;
|
||||
|
||||
/* u[5] only has 6 significant bits */
|
||||
z = u[5];
|
||||
u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[3];
|
||||
u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[2] >> 35; /* z only has 29 significant bits */
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[5] = u[4] = u[3] = 0;
|
||||
u[2] ^= z << 35;
|
||||
#else
|
||||
if (MP_USED(r) < 11) {
|
||||
MP_CHECKOK(s_mp_pad(r, 11));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 11;
|
||||
|
||||
/* u[11] only has 6 significant bits */
|
||||
z = u[10];
|
||||
u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[4] ^= (z << 29);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 28) ^ (z >> 29);
|
||||
u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[3] ^= (z << 29);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 28) ^ (z >> 29);
|
||||
u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[2] ^= (z << 29);
|
||||
z = u[7];
|
||||
u[3] ^= (z >> 28) ^ (z >> 29);
|
||||
u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[1] ^= (z << 29);
|
||||
z = u[6];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29);
|
||||
u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[0] ^= (z << 29);
|
||||
z = u[5] >> 3; /* z only has 29 significant bits */
|
||||
u[1] ^= (z >> 25) ^ (z >> 26);
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0;
|
||||
u[5] ^= z << 3;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 3) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
if (MP_USED(a) < 6) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 12) {
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
}
|
||||
MP_USED(r) = 12;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
#endif
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 163-bit curve. Assumes
|
||||
* reduction polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0;
|
||||
mp_digit rm[6];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_163_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
#endif
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
#endif
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
MP_USED(r) = 6;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3);
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1,
|
||||
b3 ^ b0);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6);
|
||||
MP_DIGIT(r, 8) ^= rm[5];
|
||||
MP_DIGIT(r, 7) ^= rm[4];
|
||||
MP_DIGIT(r, 6) ^= rm[3];
|
||||
MP_DIGIT(r, 5) ^= rm[2];
|
||||
MP_DIGIT(r, 4) ^= rm[1];
|
||||
MP_DIGIT(r, 3) ^= rm[0];
|
||||
MP_USED(r) = 12;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 163-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m163(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_163_mod;
|
||||
group->meth->field_mul = &ec_GF2m_163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_163_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 7;
|
||||
|
||||
/* u[6] only has 2 significant bits */
|
||||
z = u[6];
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 63);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 50);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 63);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 50);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 63);
|
||||
z = u[3] >> 1; /* z only has 63 significant bits */
|
||||
u[1] ^= (z >> 49);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 1;
|
||||
#else
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 13;
|
||||
|
||||
/* u[12] only has 2 significant bits */
|
||||
z = u[12];
|
||||
u[6] ^= (z << 14) ^ (z >> 1);
|
||||
u[5] ^= (z << 31);
|
||||
z = u[11];
|
||||
u[6] ^= (z >> 18);
|
||||
u[5] ^= (z << 14) ^ (z >> 1);
|
||||
u[4] ^= (z << 31);
|
||||
z = u[10];
|
||||
u[5] ^= (z >> 18);
|
||||
u[4] ^= (z << 14) ^ (z >> 1);
|
||||
u[3] ^= (z << 31);
|
||||
z = u[9];
|
||||
u[4] ^= (z >> 18);
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 31);
|
||||
z = u[8];
|
||||
u[3] ^= (z >> 18);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 31);
|
||||
z = u[7];
|
||||
u[2] ^= (z >> 18);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 31);
|
||||
z = u[6] >> 1; /* z only has 31 significant bits */
|
||||
u[1] ^= (z >> 17);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[12] = u[11] = u[10] = u[9] = u[8] = u[7] = 0;
|
||||
u[6] ^= z << 1;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
MP_USED(r) = 7;
|
||||
#else
|
||||
if (MP_USED(a) < 7) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
MP_USED(r) = 13;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
#endif
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 193-bit curve. Assumes
|
||||
* reduction polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, b6 = 0, b5 = 0, b4 = 0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_193_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 14));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 8, a6, a5, a4, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b3, b6 ^ b2, b5 ^ b1,
|
||||
b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7);
|
||||
rm[6] ^= MP_DIGIT(r, 6);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 14;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 193-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m193(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_193_mod;
|
||||
group->meth->field_mul = &ec_GF2m_193_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_193_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 8;
|
||||
|
||||
/* u[7] only has 18 significant bits */
|
||||
z = u[7];
|
||||
u[4] ^= (z << 33) ^ (z >> 41);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[6];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 33) ^ (z >> 41);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 31);
|
||||
u[2] ^= (z << 33) ^ (z >> 41);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 31);
|
||||
u[1] ^= (z << 33) ^ (z >> 41);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[3] >> 41; /* z only has 23 significant bits */
|
||||
u[1] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[7] = u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 41;
|
||||
#else
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 15;
|
||||
|
||||
/* u[14] only has 18 significant bits */
|
||||
z = u[14];
|
||||
u[9] ^= (z << 1);
|
||||
u[7] ^= (z >> 9);
|
||||
u[6] ^= (z << 23);
|
||||
z = u[13];
|
||||
u[9] ^= (z >> 31);
|
||||
u[8] ^= (z << 1);
|
||||
u[6] ^= (z >> 9);
|
||||
u[5] ^= (z << 23);
|
||||
z = u[12];
|
||||
u[8] ^= (z >> 31);
|
||||
u[7] ^= (z << 1);
|
||||
u[5] ^= (z >> 9);
|
||||
u[4] ^= (z << 23);
|
||||
z = u[11];
|
||||
u[7] ^= (z >> 31);
|
||||
u[6] ^= (z << 1);
|
||||
u[4] ^= (z >> 9);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[10];
|
||||
u[6] ^= (z >> 31);
|
||||
u[5] ^= (z << 1);
|
||||
u[3] ^= (z >> 9);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 31);
|
||||
u[4] ^= (z << 1);
|
||||
u[2] ^= (z >> 9);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 1);
|
||||
u[1] ^= (z >> 9);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[7] >> 9; /* z only has 23 significant bits */
|
||||
u[3] ^= (z >> 22);
|
||||
u[2] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[14] = u[13] = u[12] = u[11] = u[10] = u[9] = u[8] = 0;
|
||||
u[7] ^= z << 9;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
MP_USED(r) = 8;
|
||||
#else
|
||||
if (MP_USED(a) < 8) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
MP_USED(r) = 15;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[14] = gf2m_SQR0(v[7]);
|
||||
u[13] = gf2m_SQR1(v[6]);
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
#endif
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 233-bit curve. Assumes
|
||||
* reduction polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a7 = 0, a6 = 0, a5 = 0, a4 = 0, b7 = 0, b6 = 0, b5 = 0, b4 =
|
||||
0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_233_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
b7 = MP_DIGIT(b, 7);
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 16));
|
||||
s_bmul_4x4(MP_DIGITS(r) + 8, a7, a6, a5, a4, b7, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a7 ^ a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b7 ^ b3,
|
||||
b6 ^ b2, b5 ^ b1, b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7) ^ MP_DIGIT(r, 15);
|
||||
rm[6] ^= MP_DIGIT(r, 6) ^ MP_DIGIT(r, 14);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 16;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 233-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m233(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_233_mod;
|
||||
group->meth->field_mul = &ec_GF2m_233_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_233_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.2. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda));
|
||||
MP_CHECKOK(mp_init(&tempx));
|
||||
MP_CHECKOK(mp_init(&tempy));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py+qy) / (px+qx), tempx = a + lambda^2
|
||||
* + lambda + px + qx */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, qx, &tempx, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qx = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = qx + qy / qx */
|
||||
MP_CHECKOK(group->meth->field_div(qy, qx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&lambda, qx, &lambda, group->meth));
|
||||
/* tempx = a + lambda^2 + lambda */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
}
|
||||
/* ry = (qx + tempx) * lambda + tempx + qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempy, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&tempy, qy, ry, group->meth));
|
||||
/* rx = tempx */
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy));
|
||||
/* nqy = qx+qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth));
|
||||
MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group));
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return group->point_add(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err
|
||||
ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl));
|
||||
MP_CHECKOK(mp_init(&accr));
|
||||
MP_CHECKOK(mp_init(&tmp));
|
||||
MP_CHECKOK(mp_init(&pxt));
|
||||
MP_CHECKOK(mp_init(&pyt));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 + x*y */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x^2 + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
|
||||
if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery
|
||||
* projective coordinates. Uses algorithm Mdouble in appendix of Lopez, J.
|
||||
* and Dahab, R. "Fast multiplication on elliptic curves over GF(2^m)
|
||||
* without precomputation". modified to not require precomputation of
|
||||
* c=b^{2^{m-1}}. */
|
||||
static mp_err
|
||||
gf2m_Mdouble(mp_int *x, mp_int *z, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x, &t1, z, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x, &t1, x, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in
|
||||
* Montgomery projective coordinates. Uses algorithm Madd in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". */
|
||||
static mp_err
|
||||
gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1, t2;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&t2) = 0;
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
MP_CHECKOK(mp_init(&t2));
|
||||
|
||||
MP_CHECKOK(mp_copy(x, &t1));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
mp_clear(&t2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". Returns: 0 on error 1 if return value
|
||||
* should be the point at infinity 2 otherwise */
|
||||
static int
|
||||
gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
|
||||
mp_int *x2, mp_int *z2, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int ret = 0;
|
||||
mp_int t3, t4, t5;
|
||||
|
||||
MP_DIGITS(&t3) = 0;
|
||||
MP_DIGITS(&t4) = 0;
|
||||
MP_DIGITS(&t5) = 0;
|
||||
MP_CHECKOK(mp_init(&t3));
|
||||
MP_CHECKOK(mp_init(&t4));
|
||||
MP_CHECKOK(mp_init(&t5));
|
||||
|
||||
if (mp_cmp_z(z1) == 0) {
|
||||
mp_zero(x2);
|
||||
mp_zero(z2);
|
||||
ret = 1;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_z(z2) == 0) {
|
||||
MP_CHECKOK(mp_copy(x, x2));
|
||||
MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth));
|
||||
ret = 2;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_set_int(&t5, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth));
|
||||
|
||||
ret = 2;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t3);
|
||||
mp_clear(&t4);
|
||||
mp_clear(&t5);
|
||||
if (res == MP_OKAY) {
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast
|
||||
* multiplication on elliptic curves over GF(2^m) without
|
||||
* precomputation". Elliptic curve points P and R can be identical. Uses
|
||||
* Montgomery projective coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int x1, x2, z1, z2;
|
||||
int i, j;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&x1));
|
||||
MP_CHECKOK(mp_init(&x2));
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */
|
||||
MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 =
|
||||
* x1^2 =
|
||||
* px^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2
|
||||
* =
|
||||
* px^4
|
||||
* +
|
||||
* b
|
||||
*/
|
||||
|
||||
/* find top-most bit and go one past it */
|
||||
i = MP_USED(n) - 1;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
while (!(MP_DIGITS(n)[i] & mask)) {
|
||||
mask >>= 1;
|
||||
j--;
|
||||
}
|
||||
mask >>= 1;
|
||||
j--;
|
||||
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
for (; j >= 0; j--) {
|
||||
if (MP_DIGITS(n)[i] & mask) {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group));
|
||||
} else {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group));
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group);
|
||||
if (i == 0) {
|
||||
res = MP_BADARG;
|
||||
goto CLEANUP;
|
||||
} else if (i == 1) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&x2, rx));
|
||||
MP_CHECKOK(mp_copy(&z2, ry));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
||||
@@ -1,369 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* by default, these routines are unused and thus don't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). P and R can share x and y coordinates. Assumes
|
||||
* input is already field-encoded using field_enc, and returns output that
|
||||
* is still field-encoded. */
|
||||
mp_err
|
||||
ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz, py / pz^2) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z1, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z2, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed projective-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (3) from Hankerson, Hernandez, Menezes.
|
||||
* Software Implementation of Elliptic Curve Cryptography Over Binary
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, E, F, G;
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
return ec_GF2m_pt_aff2proj(qx, qy, rx, ry, rz, group);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
return mp_copy(pz, rz);
|
||||
}
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&E) = 0;
|
||||
MP_DIGITS(&F) = 0;
|
||||
MP_DIGITS(&G) = 0;
|
||||
MP_CHECKOK(mp_init(&A));
|
||||
MP_CHECKOK(mp_init(&B));
|
||||
MP_CHECKOK(mp_init(&C));
|
||||
MP_CHECKOK(mp_init(&D));
|
||||
MP_CHECKOK(mp_init(&E));
|
||||
MP_CHECKOK(mp_init(&F));
|
||||
MP_CHECKOK(mp_init(&G));
|
||||
|
||||
/* D = pz^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &D, group->meth));
|
||||
|
||||
/* A = qy * pz^2 + py */
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &D, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&A, py, &A, group->meth));
|
||||
|
||||
/* B = qx * pz + px */
|
||||
MP_CHECKOK(group->meth->field_mul(qx, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&B, px, &B, group->meth));
|
||||
|
||||
/* C = pz * B */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &B, &C, group->meth));
|
||||
|
||||
/* D = B^2 * (C + a * pz^2) (using E as a temporary variable) */
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curvea, &D, &D, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C, &D, &D, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&B, &E, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&E, &D, &D, group->meth));
|
||||
|
||||
/* rz = C^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, rz, group->meth));
|
||||
|
||||
/* E = A * C */
|
||||
MP_CHECKOK(group->meth->field_mul(&A, &C, &E, group->meth));
|
||||
|
||||
/* rx = A^2 + D + E */
|
||||
MP_CHECKOK(group->meth->field_sqr(&A, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &D, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &E, rx, group->meth));
|
||||
|
||||
/* F = rx + qx * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(qx, rz, &F, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &F, &F, group->meth));
|
||||
|
||||
/* G = rx + qy * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(qy, rz, &G, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &G, &G, group->meth));
|
||||
|
||||
/* ry = E * F + rz * G (using G as a temporary variable) */
|
||||
MP_CHECKOK(group->meth->field_mul(rz, &G, &G, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&E, &F, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(ry, &G, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&E);
|
||||
mp_clear(&F);
|
||||
mp_clear(&G);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* projective coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* Uses equation (3) from Hankerson, Hernandez, Menezes. Software
|
||||
* Implementation of Elliptic Curve Cryptography Over Binary Fields.
|
||||
*/
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1;
|
||||
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
return ec_GF2m_pt_set_inf_proj(rx, ry, rz);
|
||||
}
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t0));
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
|
||||
/* t0 = px^2 */
|
||||
/* t1 = pz^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &t1, group->meth));
|
||||
|
||||
/* rz = px^2 * pz^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, rz, group->meth));
|
||||
|
||||
/* t0 = px^4 */
|
||||
/* t1 = b * pz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
|
||||
/* rx = px^4 + b * pz^4 */
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t1, rx, group->meth));
|
||||
|
||||
/* ry = b * pz^4 * rz + rx * (a * rz + py^2 + b * pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(ry, &t1, ry, group->meth));
|
||||
/* t0 = a * rz */
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curvea, rz, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(rx, ry, ry, group->meth));
|
||||
/* t1 = b * pz^4 * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(&t1, rz, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t1, ry, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed projective-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 16 * 2], *t;
|
||||
int i, ni, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
t = precomp_arr;
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* x co-ord */
|
||||
MP_SIGN(&precomp[i][0]) = MP_ZPOS;
|
||||
MP_ALLOC(&precomp[i][0]) = ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
MP_USED(&precomp[i][0]) = 1;
|
||||
*t = 0;
|
||||
MP_DIGITS(&precomp[i][0]) = t;
|
||||
t += ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
/* y co-ord */
|
||||
MP_SIGN(&precomp[i][1]) = MP_ZPOS;
|
||||
MP_ALLOC(&precomp[i][1]) = ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
MP_USED(&precomp[i][1]) = 1;
|
||||
*t = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = t;
|
||||
t += ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_proj(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GF2m_pt_add_proj
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GF2m_pt_proj2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int
|
||||
ec_twoTo(int e)
|
||||
{
|
||||
int a = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < e; i++) {
|
||||
a *= 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err
|
||||
ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in, int w)
|
||||
{
|
||||
mp_int k;
|
||||
mp_err res = MP_OKAY;
|
||||
int i, twowm1, mask;
|
||||
|
||||
twowm1 = ec_twoTo(w - 1);
|
||||
mask = 2 * twowm1 - 1;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_CHECKOK(mp_init_copy(&k, in));
|
||||
|
||||
i = 0;
|
||||
/* Compute wNAF form */
|
||||
while (mp_cmp_z(&k) > 0) {
|
||||
if (mp_isodd(&k)) {
|
||||
out[i] = MP_DIGIT(&k, 0) & mask;
|
||||
if (out[i] >= twowm1)
|
||||
out[i] -= 2 * twowm1;
|
||||
|
||||
/* Subtract off out[i]. Note mp_sub_d only works with
|
||||
* unsigned digits */
|
||||
if (out[i] >= 0) {
|
||||
mp_sub_d(&k, out[i], &k);
|
||||
} else {
|
||||
mp_add_d(&k, -(out[i]), &k);
|
||||
}
|
||||
} else {
|
||||
out[i] = 0;
|
||||
}
|
||||
mp_div_2(&k, &k);
|
||||
i++;
|
||||
}
|
||||
/* Zero out the remaining elements of the out array. */
|
||||
for (; i < bitsize + 1; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
return res;
|
||||
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ecl_curve_h_
|
||||
#define __ecl_curve_h_
|
||||
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
#error This source file is for Basic ECC only .
|
||||
#endif
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P256 = {
|
||||
"NIST-P256", ECField_GFp, 256,
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P384 = {
|
||||
"NIST-P384", ECField_GFp, 384,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||
1
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P521 = {
|
||||
"NIST-P521", ECField_GFp, 521,
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||
1
|
||||
};
|
||||
|
||||
/* mapping between ECCurveName enum and pointers to ECCurveParams */
|
||||
static const ECCurveParams *ecCurve_map[] = {
|
||||
NULL, /* ECCurve_noName */
|
||||
NULL, /* ECCurve_NIST_P192 */
|
||||
NULL, /* ECCurve_NIST_P224 */
|
||||
&ecCurve_NIST_P256, /* ECCurve_NIST_P256 */
|
||||
&ecCurve_NIST_P384, /* ECCurve_NIST_P384 */
|
||||
&ecCurve_NIST_P521, /* ECCurve_NIST_P521 */
|
||||
NULL, /* ECCurve_NIST_K163 */
|
||||
NULL, /* ECCurve_NIST_B163 */
|
||||
NULL, /* ECCurve_NIST_K233 */
|
||||
NULL, /* ECCurve_NIST_B233 */
|
||||
NULL, /* ECCurve_NIST_K283 */
|
||||
NULL, /* ECCurve_NIST_B283 */
|
||||
NULL, /* ECCurve_NIST_K409 */
|
||||
NULL, /* ECCurve_NIST_B409 */
|
||||
NULL, /* ECCurve_NIST_K571 */
|
||||
NULL, /* ECCurve_NIST_B571 */
|
||||
NULL, /* ECCurve_X9_62_PRIME_192V2 */
|
||||
NULL, /* ECCurve_X9_62_PRIME_192V3 */
|
||||
NULL, /* ECCurve_X9_62_PRIME_239V1 */
|
||||
NULL, /* ECCurve_X9_62_PRIME_239V2 */
|
||||
NULL, /* ECCurve_X9_62_PRIME_239V3 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB163V2 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB163V3 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB176V1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB191V1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB191V2 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB191V3 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB208W1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB239V1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB239V2 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB239V3 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB272W1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB304W1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB359V1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_PNB368W1 */
|
||||
NULL, /* ECCurve_X9_62_CHAR2_TNB431R1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_112R1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_112R2 */
|
||||
NULL, /* ECCurve_SECG_PRIME_128R1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_128R2 */
|
||||
NULL, /* ECCurve_SECG_PRIME_160K1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_160R1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_160R2 */
|
||||
NULL, /* ECCurve_SECG_PRIME_192K1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_224K1 */
|
||||
NULL, /* ECCurve_SECG_PRIME_256K1 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_113R1 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_113R2 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_131R1 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_131R2 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_163R1 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_193R1 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_193R2 */
|
||||
NULL, /* ECCurve_SECG_CHAR2_239K1 */
|
||||
NULL, /* ECCurve_WTLS_1 */
|
||||
NULL, /* ECCurve_WTLS_8 */
|
||||
NULL, /* ECCurve_WTLS_9 */
|
||||
NULL /* ECCurve_pastLastCurve */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecl_exp_h_
|
||||
#define __ecl_exp_h_
|
||||
|
||||
/* Curve field type */
|
||||
typedef enum {
|
||||
ECField_GFp,
|
||||
ECField_GF2m
|
||||
} ECField;
|
||||
|
||||
/* Hexadecimal encoding of curve parameters */
|
||||
struct ECCurveParamsStr {
|
||||
char *text;
|
||||
ECField field;
|
||||
unsigned int size;
|
||||
char *irr;
|
||||
char *curvea;
|
||||
char *curveb;
|
||||
char *genx;
|
||||
char *geny;
|
||||
char *order;
|
||||
int cofactor;
|
||||
};
|
||||
typedef struct ECCurveParamsStr ECCurveParams;
|
||||
|
||||
/* Named curve parameters */
|
||||
typedef enum {
|
||||
|
||||
ECCurve_noName = 0,
|
||||
|
||||
/* NIST prime curves */
|
||||
ECCurve_NIST_P192,
|
||||
ECCurve_NIST_P224,
|
||||
ECCurve_NIST_P256,
|
||||
ECCurve_NIST_P384,
|
||||
ECCurve_NIST_P521,
|
||||
|
||||
/* NIST binary curves */
|
||||
ECCurve_NIST_K163,
|
||||
ECCurve_NIST_B163,
|
||||
ECCurve_NIST_K233,
|
||||
ECCurve_NIST_B233,
|
||||
ECCurve_NIST_K283,
|
||||
ECCurve_NIST_B283,
|
||||
ECCurve_NIST_K409,
|
||||
ECCurve_NIST_B409,
|
||||
ECCurve_NIST_K571,
|
||||
ECCurve_NIST_B571,
|
||||
|
||||
/* ANSI X9.62 prime curves */
|
||||
/* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */
|
||||
ECCurve_X9_62_PRIME_192V2,
|
||||
ECCurve_X9_62_PRIME_192V3,
|
||||
ECCurve_X9_62_PRIME_239V1,
|
||||
ECCurve_X9_62_PRIME_239V2,
|
||||
ECCurve_X9_62_PRIME_239V3,
|
||||
/* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */
|
||||
|
||||
/* ANSI X9.62 binary curves */
|
||||
ECCurve_X9_62_CHAR2_PNB163V1,
|
||||
ECCurve_X9_62_CHAR2_PNB163V2,
|
||||
ECCurve_X9_62_CHAR2_PNB163V3,
|
||||
ECCurve_X9_62_CHAR2_PNB176V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V2,
|
||||
ECCurve_X9_62_CHAR2_TNB191V3,
|
||||
ECCurve_X9_62_CHAR2_PNB208W1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V2,
|
||||
ECCurve_X9_62_CHAR2_TNB239V3,
|
||||
ECCurve_X9_62_CHAR2_PNB272W1,
|
||||
ECCurve_X9_62_CHAR2_PNB304W1,
|
||||
ECCurve_X9_62_CHAR2_TNB359V1,
|
||||
ECCurve_X9_62_CHAR2_PNB368W1,
|
||||
ECCurve_X9_62_CHAR2_TNB431R1,
|
||||
|
||||
/* SEC2 prime curves */
|
||||
ECCurve_SECG_PRIME_112R1,
|
||||
ECCurve_SECG_PRIME_112R2,
|
||||
ECCurve_SECG_PRIME_128R1,
|
||||
ECCurve_SECG_PRIME_128R2,
|
||||
ECCurve_SECG_PRIME_160K1,
|
||||
ECCurve_SECG_PRIME_160R1,
|
||||
ECCurve_SECG_PRIME_160R2,
|
||||
ECCurve_SECG_PRIME_192K1,
|
||||
/* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */
|
||||
ECCurve_SECG_PRIME_224K1,
|
||||
/* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */
|
||||
ECCurve_SECG_PRIME_256K1,
|
||||
/* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */
|
||||
/* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */
|
||||
/* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */
|
||||
|
||||
/* SEC2 binary curves */
|
||||
ECCurve_SECG_CHAR2_113R1,
|
||||
ECCurve_SECG_CHAR2_113R2,
|
||||
ECCurve_SECG_CHAR2_131R1,
|
||||
ECCurve_SECG_CHAR2_131R2,
|
||||
/* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */
|
||||
ECCurve_SECG_CHAR2_163R1,
|
||||
/* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */
|
||||
ECCurve_SECG_CHAR2_193R1,
|
||||
ECCurve_SECG_CHAR2_193R2,
|
||||
/* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */
|
||||
ECCurve_SECG_CHAR2_239K1,
|
||||
/* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */
|
||||
/* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */
|
||||
/* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */
|
||||
/* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */
|
||||
/* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */
|
||||
/* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */
|
||||
|
||||
/* WTLS curves */
|
||||
ECCurve_WTLS_1,
|
||||
/* there is no WTLS 2 curve */
|
||||
/* ECCurve_WTLS_3 == ECCurve_NIST_K163 */
|
||||
/* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */
|
||||
/* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
/* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */
|
||||
/* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */
|
||||
ECCurve_WTLS_8,
|
||||
ECCurve_WTLS_9,
|
||||
/* ECCurve_WTLS_10 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
|
||||
/* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
|
||||
|
||||
ECCurve_pastLastCurve
|
||||
} ECCurveName;
|
||||
|
||||
/* Aliased named curves */
|
||||
|
||||
#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192
|
||||
#define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192
|
||||
#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224
|
||||
#define ECCurve_SECG_PRIME_256R1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_384R1 ECCurve_NIST_P384
|
||||
#define ECCurve_SECG_PRIME_521R1 ECCurve_NIST_P521
|
||||
#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163
|
||||
#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163
|
||||
#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233
|
||||
#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233
|
||||
#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283
|
||||
#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283
|
||||
#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409
|
||||
#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409
|
||||
#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571
|
||||
#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571
|
||||
#define ECCurve_WTLS_3 ECCurve_NIST_K163
|
||||
#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1
|
||||
#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1
|
||||
#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1
|
||||
#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1
|
||||
#define ECCurve_WTLS_10 ECCurve_NIST_K233
|
||||
#define ECCurve_WTLS_11 ECCurve_NIST_B233
|
||||
#define ECCurve_WTLS_12 ECCurve_NIST_P224
|
||||
|
||||
#endif /* __ecl_exp_h_ */
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecl_priv_h_
|
||||
#define __ecl_priv_h_
|
||||
|
||||
#include "ecl.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
|
||||
/* the following needs to go away... */
|
||||
#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
|
||||
#define ECL_SIXTY_FOUR_BIT
|
||||
#else
|
||||
#define ECL_THIRTY_TWO_BIT
|
||||
#endif
|
||||
|
||||
#define ECL_CURVE_DIGITS(curve_size_in_bits) \
|
||||
(((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8))
|
||||
#define ECL_BITS (sizeof(mp_digit)*8)
|
||||
#define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit))
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a. If i >= length(a),
|
||||
* then return 0. (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).) */
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(cin)) + (a1) + (a2); \
|
||||
s = ACCUM(w); \
|
||||
cout = CARRYOUT(w); }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(a1)) - (a2) - (bin); \
|
||||
s = ACCUM(w); \
|
||||
bout = (w >> MP_DIGIT_BIT) & 1; }
|
||||
|
||||
#else
|
||||
/* NOTE,
|
||||
* cin and cout could be the same variable.
|
||||
* bin and bout could be the same variable.
|
||||
* a1 or a2 and s could be the same variable.
|
||||
* don't trash those outputs until their respective inputs have
|
||||
* been read. */
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_digit tmp,sum; \
|
||||
tmp = (a1); \
|
||||
sum = tmp + (a2); \
|
||||
tmp = (sum < tmp); /* detect overflow */ \
|
||||
s = sum += (cin); \
|
||||
cout = tmp + (sum < (cin)); }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_digit tmp; \
|
||||
tmp = (a1); \
|
||||
s = tmp - (a2); \
|
||||
tmp = (s > tmp); /* detect borrow */ \
|
||||
if ((bin) && !s--) tmp++; \
|
||||
bout = tmp; }
|
||||
#endif
|
||||
|
||||
|
||||
struct GFMethodStr;
|
||||
typedef struct GFMethodStr GFMethod;
|
||||
struct GFMethodStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Irreducible that defines the field. For prime fields, this is the
|
||||
* prime p. For binary polynomial fields, this is the bitstring
|
||||
* representation of the irreducible polynomial. */
|
||||
mp_int irr;
|
||||
/* For prime fields, the value irr_arr[0] is the number of bits in the
|
||||
* field. For binary polynomial fields, the irreducible polynomial
|
||||
* f(t) is represented as an array of unsigned int[], where f(t) is
|
||||
* of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0]
|
||||
* > p[1] > ... > p[4] = 0. */
|
||||
unsigned int irr_arr[5];
|
||||
/* Field arithmetic methods. All methods (except field_enc and
|
||||
* field_dec) are assumed to take field-encoded parameters and return
|
||||
* field-encoded values. All methods (except field_enc and field_dec)
|
||||
* are required to be implemented. */
|
||||
mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (GFMethod *meth);
|
||||
};
|
||||
|
||||
/* Construct generic GFMethods. */
|
||||
GFMethod *GFMethod_consGFp(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGFp_mont(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGF2m(const mp_int *irr,
|
||||
const unsigned int irr_arr[5]);
|
||||
/* Free the memory allocated (if any) to a GFMethod object. */
|
||||
void GFMethod_free(GFMethod *meth);
|
||||
|
||||
struct ECGroupStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Field definition and arithmetic. */
|
||||
GFMethod *meth;
|
||||
/* Textual representation of curve name, if any. */
|
||||
char *text;
|
||||
/* Curve parameters, field-encoded. */
|
||||
mp_int curvea, curveb;
|
||||
/* x and y coordinates of the base point, field-encoded. */
|
||||
mp_int genx, geny;
|
||||
/* Order and cofactor of the base point. */
|
||||
mp_int order;
|
||||
int cofactor;
|
||||
/* Point arithmetic methods. All methods are assumed to take
|
||||
* field-encoded parameters and return field-encoded values. All
|
||||
* methods (except base_point_mul and points_mul) are required to be
|
||||
* implemented. */
|
||||
mp_err (*point_add) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_sub) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_mul) (const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (ECGroup *group);
|
||||
};
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* fixed length in-line adds. Count is in words */
|
||||
mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
/* Wrapper functions for generic binary polynomial field arithmetic. */
|
||||
mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* Montgomery prime field arithmetic. */
|
||||
mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
void ec_GFp_extra_free_mont(GFMethod *meth);
|
||||
|
||||
/* point multiplication */
|
||||
mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in,
|
||||
int w);
|
||||
|
||||
/* Optimized field arithmetic */
|
||||
mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp224(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp256(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp521(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gf2m163(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m193(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
|
||||
|
||||
/* Optimized floating-point arithmetic */
|
||||
#ifdef ECL_USE_FP
|
||||
mp_err ec_group_set_secp160r1_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp192_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp224_fp(ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* __ecl_priv_h_ */
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ec2.h"
|
||||
#include "ecp.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Allocate memory for a new ECGroup object. */
|
||||
ECGroup *
|
||||
ECGroup_new()
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group;
|
||||
group = (ECGroup *) malloc(sizeof(ECGroup));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
group->constructed = MP_YES;
|
||||
group->meth = NULL;
|
||||
group->text = NULL;
|
||||
MP_DIGITS(&group->curvea) = 0;
|
||||
MP_DIGITS(&group->curveb) = 0;
|
||||
MP_DIGITS(&group->genx) = 0;
|
||||
MP_DIGITS(&group->geny) = 0;
|
||||
MP_DIGITS(&group->order) = 0;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = NULL;
|
||||
group->validate_point = NULL;
|
||||
group->extra1 = NULL;
|
||||
group->extra2 = NULL;
|
||||
group->extra_free = NULL;
|
||||
MP_CHECKOK(mp_init(&group->curvea));
|
||||
MP_CHECKOK(mp_init(&group->curveb));
|
||||
MP_CHECKOK(mp_init(&group->genx));
|
||||
MP_CHECKOK(mp_init(&group->geny));
|
||||
MP_CHECKOK(mp_init(&group->order));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields with
|
||||
* field arithmetic implemented in Montgomery coordinates. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp_mont(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curvea, &group->curvea, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curveb, &group->curveb, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
/* Construct a generic ECGroup for elliptic curves over binary polynomial
|
||||
* fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],
|
||||
const mp_int *curvea, const mp_int *curveb,
|
||||
const mp_int *genx, const mp_int *geny,
|
||||
const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGF2m(irr, irr_arr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GF2m_pt_add_aff;
|
||||
group->point_sub = &ec_GF2m_pt_sub_aff;
|
||||
group->point_dbl = &ec_GF2m_pt_dbl_aff;
|
||||
group->point_mul = &ec_GF2m_pt_mul_mont;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->validate_point = &ec_GF2m_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Construct ECGroup from hex parameters and name, if any. Called by
|
||||
* ECGroup_fromHex and ECGroup_fromName. */
|
||||
ECGroup *
|
||||
ecgroup_fromNameAndHex(const ECCurveName name,
|
||||
const ECCurveParams * params)
|
||||
{
|
||||
mp_int irr, curvea, curveb, genx, geny, order;
|
||||
int bits;
|
||||
ECGroup *group = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* initialize values */
|
||||
MP_DIGITS(&irr) = 0;
|
||||
MP_DIGITS(&curvea) = 0;
|
||||
MP_DIGITS(&curveb) = 0;
|
||||
MP_DIGITS(&genx) = 0;
|
||||
MP_DIGITS(&geny) = 0;
|
||||
MP_DIGITS(&order) = 0;
|
||||
MP_CHECKOK(mp_init(&irr));
|
||||
MP_CHECKOK(mp_init(&curvea));
|
||||
MP_CHECKOK(mp_init(&curveb));
|
||||
MP_CHECKOK(mp_init(&genx));
|
||||
MP_CHECKOK(mp_init(&geny));
|
||||
MP_CHECKOK(mp_init(&order));
|
||||
MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
|
||||
MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
|
||||
MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
|
||||
MP_CHECKOK(mp_read_radix(&order, params->order, 16));
|
||||
|
||||
/* determine number of bits */
|
||||
bits = mpl_significant_bits(&irr) - 1;
|
||||
if (bits < MP_OKAY) {
|
||||
res = bits;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* determine which optimizations (if any) to use */
|
||||
if (params->field == ECField_GFp) {
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
switch (name) {
|
||||
#ifdef ECL_USE_FP
|
||||
case ECCurve_SECG_PRIME_160R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_secp160r1_fp(group));
|
||||
break;
|
||||
#endif
|
||||
case ECCurve_SECG_PRIME_192R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp192_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp192(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_224R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp224_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp224(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_256R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp256(group, name));
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp521(group, name));
|
||||
break;
|
||||
default:
|
||||
/* use generic arithmetic */
|
||||
#endif
|
||||
group =
|
||||
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
}
|
||||
} else if (params->field == ECField_GF2m) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
if ((name == ECCurve_NIST_K163) ||
|
||||
(name == ECCurve_NIST_B163) ||
|
||||
(name == ECCurve_SECG_CHAR2_163R1)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m163(group, name));
|
||||
} else if ((name == ECCurve_SECG_CHAR2_193R1) ||
|
||||
(name == ECCurve_SECG_CHAR2_193R2)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m193(group, name));
|
||||
} else if ((name == ECCurve_NIST_K233) ||
|
||||
(name == ECCurve_NIST_B233)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m233(group, name));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* set name, if any */
|
||||
if ((group != NULL) && (params->text != NULL)) {
|
||||
group->text = strdup(params->text);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&irr);
|
||||
mp_clear(&curvea);
|
||||
mp_clear(&curveb);
|
||||
mp_clear(&genx);
|
||||
mp_clear(&geny);
|
||||
mp_clear(&order);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromHex(const ECCurveParams * params)
|
||||
{
|
||||
return ecgroup_fromNameAndHex(ECCurve_noName, params);
|
||||
}
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromName(const ECCurveName name)
|
||||
{
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
params = EC_GetNamedCurveParams(name);
|
||||
if (params == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* construct actual group */
|
||||
group = ecgroup_fromNameAndHex(name, params);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py)
|
||||
{
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
return group->validate_point(px, py, group);
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECGroup object. */
|
||||
void
|
||||
ECGroup_free(ECGroup *group)
|
||||
{
|
||||
if (group == NULL)
|
||||
return;
|
||||
GFMethod_free(group->meth);
|
||||
if (group->constructed == MP_NO)
|
||||
return;
|
||||
mp_clear(&group->curvea);
|
||||
mp_clear(&group->curveb);
|
||||
mp_clear(&group->genx);
|
||||
mp_clear(&group->geny);
|
||||
mp_clear(&group->order);
|
||||
if (group->text != NULL)
|
||||
free(group->text);
|
||||
if (group->extra_free != NULL)
|
||||
group->extra_free(group);
|
||||
free(group);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Although this is not an exported header file, code which uses elliptic
|
||||
* curve point operations will need to include it. */
|
||||
|
||||
#ifndef __ecl_h_
|
||||
#define __ecl_h_
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include "mpi.h"
|
||||
|
||||
struct ECGroupStr;
|
||||
typedef struct ECGroupStr ECGroup;
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *ECGroup_fromHex(const ECCurveParams * params);
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *ECGroup_fromName(const ECCurveName name);
|
||||
|
||||
/* Free an allocated ECGroup. */
|
||||
void ECGroup_free(ECGroup *group);
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *ECCurveParams_dup(const ECCurveParams * params);
|
||||
|
||||
/* Free an allocated ECCurveParams */
|
||||
void EC_FreeCurveParams(ECCurveParams * params);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *qx, mp_int *qy);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Input and output values are assumed to
|
||||
* be NOT field-encoded. */
|
||||
mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
|
||||
const mp_int *k2, const mp_int *px, const mp_int *py,
|
||||
mp_int *qx, mp_int *qy);
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62.
|
||||
* Returns MP_YES if the public key is valid, MP_NO if the public key
|
||||
* is invalid, or an error code if the validation could not be
|
||||
* performed. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py);
|
||||
|
||||
#endif /* __ecl_h_ */
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; }
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *
|
||||
ECCurveParams_dup(const ECCurveParams * params)
|
||||
{
|
||||
int res = 1;
|
||||
ECCurveParams *ret = NULL;
|
||||
|
||||
CHECK(ret = (ECCurveParams *) calloc(1, sizeof(ECCurveParams)));
|
||||
if (params->text != NULL) {
|
||||
CHECK(ret->text = strdup(params->text));
|
||||
}
|
||||
ret->field = params->field;
|
||||
ret->size = params->size;
|
||||
if (params->irr != NULL) {
|
||||
CHECK(ret->irr = strdup(params->irr));
|
||||
}
|
||||
if (params->curvea != NULL) {
|
||||
CHECK(ret->curvea = strdup(params->curvea));
|
||||
}
|
||||
if (params->curveb != NULL) {
|
||||
CHECK(ret->curveb = strdup(params->curveb));
|
||||
}
|
||||
if (params->genx != NULL) {
|
||||
CHECK(ret->genx = strdup(params->genx));
|
||||
}
|
||||
if (params->geny != NULL) {
|
||||
CHECK(ret->geny = strdup(params->geny));
|
||||
}
|
||||
if (params->order != NULL) {
|
||||
CHECK(ret->order = strdup(params->order));
|
||||
}
|
||||
ret->cofactor = params->cofactor;
|
||||
|
||||
CLEANUP:
|
||||
if (res != 1) {
|
||||
EC_FreeCurveParams(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *
|
||||
EC_GetNamedCurveParams(const ECCurveName name)
|
||||
{
|
||||
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
|
||||
(ecCurve_map[name] == NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ECCurveParams_dup(ecCurve_map[name]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECCurveParams object. */
|
||||
void
|
||||
EC_FreeCurveParams(ECCurveParams * params)
|
||||
{
|
||||
if (params == NULL)
|
||||
return;
|
||||
if (params->text != NULL)
|
||||
free(params->text);
|
||||
if (params->irr != NULL)
|
||||
free(params->irr);
|
||||
if (params->curvea != NULL)
|
||||
free(params->curvea);
|
||||
if (params->curveb != NULL)
|
||||
free(params->curveb);
|
||||
if (params->genx != NULL)
|
||||
free(params->genx);
|
||||
if (params->geny != NULL)
|
||||
free(params->geny);
|
||||
if (params->order != NULL)
|
||||
free(params->order);
|
||||
free(params);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int kt;
|
||||
|
||||
ARGCHK((k != NULL) && (group != NULL), MP_BADARG);
|
||||
MP_DIGITS(&kt) = 0;
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (mp_cmp(k, &group->order) > 0) {
|
||||
MP_CHECKOK(mp_init(&kt));
|
||||
MP_CHECKOK(mp_mod(k, &group->order, &kt));
|
||||
} else {
|
||||
MP_SIGN(&kt) = MP_ZPOS;
|
||||
MP_USED(&kt) = MP_USED(k);
|
||||
MP_ALLOC(&kt) = MP_ALLOC(k);
|
||||
MP_DIGITS(&kt) = MP_DIGITS(k);
|
||||
}
|
||||
|
||||
if ((px == NULL) || (py == NULL)) {
|
||||
if (group->base_point_mul) {
|
||||
MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group));
|
||||
} else {
|
||||
MP_CHECKOK(group->
|
||||
point_mul(&kt, &group->genx, &group->geny, rx, ry,
|
||||
group));
|
||||
}
|
||||
} else {
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(py, ry, group->meth));
|
||||
MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group));
|
||||
} else {
|
||||
MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group));
|
||||
}
|
||||
}
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if (MP_DIGITS(&kt) != MP_DIGITS(k)) {
|
||||
mp_clear(&kt);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy));
|
||||
MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry));
|
||||
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. Uses
|
||||
* algorithm 15 (simultaneous multiple point multiplication) from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST
|
||||
* Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][0],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS) );
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][1],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS) );
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(group->
|
||||
point_add(rx, ry, &precomp[ai][bi][0],
|
||||
&precomp[ai][bi][1], rx, ry, group));
|
||||
}
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k1t, k2t;
|
||||
const mp_int *k1p, *k2p;
|
||||
|
||||
MP_DIGITS(&k1t) = 0;
|
||||
MP_DIGITS(&k2t) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (k1 != NULL) {
|
||||
if (mp_cmp(k1, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k1t));
|
||||
MP_CHECKOK(mp_mod(k1, &group->order, &k1t));
|
||||
k1p = &k1t;
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
if (k2 != NULL) {
|
||||
if (mp_cmp(k2, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k2t));
|
||||
MP_CHECKOK(mp_mod(k2, &group->order, &k2t));
|
||||
k2p = &k2t;
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
|
||||
/* if points_mul is defined, then use it */
|
||||
if (group->points_mul) {
|
||||
res = group->points_mul(k1p, k2p, px, py, rx, ry, group);
|
||||
} else {
|
||||
res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k1t);
|
||||
mp_clear(&k2t);
|
||||
return res;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecp_h_
|
||||
#define __ecp_h_
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). */
|
||||
mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R(x, y) = k1 * G + k2 * P(x, y), where G is the generator
|
||||
* (base point) of the group of points on the elliptic curve. Allows k1 =
|
||||
* NULL or { k2, P } = NULL. Implemented using mixed Jacobian-affine
|
||||
* coordinates. Input and output values are assumed to be NOT
|
||||
* field-encoded and are in affine form. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
#endif /* __ecp_h_ */
|
||||
@@ -1,516 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP192_DIGITS ECL_CURVE_DIGITS(192)
|
||||
|
||||
/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
mp_digit r3;
|
||||
#ifndef MPI_AMD64_ADD
|
||||
mp_digit carry;
|
||||
#endif
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b;
|
||||
#else
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0;
|
||||
mp_digit r0, r1, r2;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP192_DIGITS) {
|
||||
if (a == r) {
|
||||
return MP_OKAY;
|
||||
}
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECP192_DIGITS*2) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
/* copy out upper words of a */
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
|
||||
/* in all the math below,
|
||||
* nXb is most signifiant, nXa is least significant */
|
||||
switch (a_used) {
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a3a = MP_DIGIT(a, 6);
|
||||
}
|
||||
|
||||
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
MP_ADD_CARRY(r0a, a3a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a3b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a3a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a3b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a4b, r2b, carry, carry);
|
||||
r3 = carry; carry = 0;
|
||||
MP_ADD_CARRY(r0a, a5a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a5b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a5a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a5b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a5a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a5b, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1a, a4a, r1a, 0, carry);
|
||||
MP_ADD_CARRY(r1b, a4b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
MP_ADD_CARRY(r0a, r3, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, r3, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, 0, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 = carry;
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (((r2b == 0xffffffff) && (r2a == 0xffffffff)
|
||||
&& (r1b == 0xffffffff) ) &&
|
||||
((r1a == 0xffffffff) ||
|
||||
(r1a == 0xfffffffe) && (r0a == 0xffffffff) &&
|
||||
(r0b == 0xffffffff)) ) {
|
||||
/* do a quick subtract */
|
||||
MP_ADD_CARRY(r0a, 1, r0a, 0, carry);
|
||||
r0b += carry;
|
||||
r1a = r1b = r2a = r2b = 0;
|
||||
}
|
||||
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
}
|
||||
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, a3, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a4, r2, carry, carry);
|
||||
r3 = carry;
|
||||
MP_ADD_CARRY(r0, a5, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a5, r2, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1, a4, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
#else
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* set the lower words of r */
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq %5,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %6,%0 \n\t"
|
||||
"adcq %6,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %5,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3),
|
||||
"=r"(a4), "=r"(a5)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3),
|
||||
"4" (a3), "5" (a4), "6"(a5)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, r3, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, r3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 = carry;
|
||||
#else
|
||||
a3=r3;
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (r3 || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
/* do a quick subtract */
|
||||
r0++;
|
||||
r1 = r2 = 0;
|
||||
}
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
}
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_USED(r) = 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
/* Compute the sum of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a0 = 0, a1 = 0, a2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit carry;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
a0 = MP_DIGIT(a,0);
|
||||
}
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(a0, r0, r0, 0, carry);
|
||||
MP_ADD_CARRY(a1, r1, r1, carry, carry);
|
||||
MP_ADD_CARRY(a2, r2, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %5,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
|
||||
: "r" (a0), "r" (a1), "r" (a2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'subract' if we've gone over
|
||||
* (add the 2's complement of the curve field) */
|
||||
if (carry || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, 1, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 1, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"addq $1,%0 \n\t"
|
||||
"adcq $1,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the diff of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit b0 = 0, b1 = 0, b2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit borrow;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(a,0);
|
||||
}
|
||||
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
b0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, b0, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"subq %4,%0 \n\t"
|
||||
"sbbq %5,%1 \n\t"
|
||||
"sbbq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow)
|
||||
: "r" (b0), "r" (b1), "r" (b2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'add' if we've gone under 0
|
||||
* (subtract the 2's complement of the curve field) */
|
||||
if (borrow) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, 1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, 0, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"subq $1,%0 \n\t"
|
||||
"sbbq $1,%1 \n\t"
|
||||
"sbbq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p192. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p192.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p192. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp192(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P192) {
|
||||
group->meth->field_mod = &ec_GFp_nistp192_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp192_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp192_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp192_div;
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
group->meth->field_add = &ec_GFp_nistp192_add;
|
||||
group->meth->field_sub = &ec_GFp_nistp192_sub;
|
||||
#endif
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP224_DIGITS ECL_CURVE_DIGITS(224)
|
||||
|
||||
/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
|
||||
int r3b;
|
||||
mp_digit carry;
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6a = 0, a6b = 0,
|
||||
a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
|
||||
#else
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
|
||||
mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP224_DIGITS) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECL_CURVE_DIGITS(224*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 14:
|
||||
a6b = MP_DIGIT(a, 13);
|
||||
case 13:
|
||||
a6a = MP_DIGIT(a, 12);
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
}
|
||||
r3a = MP_DIGIT(a, 6);
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1b, a3b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
|
||||
r3b = carry;
|
||||
MP_ADD_CARRY (r1b, a5b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, 0, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
MP_SUB_BORROW(r0a, a3b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
MP_SUB_BORROW(r0a, a5b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
}
|
||||
|
||||
while (r3b > 0) {
|
||||
int tmp;
|
||||
MP_ADD_CARRY(r1b, r3b, r1b, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
MP_ADD_CARRY(r3a, 0, r3a, carry, carry);
|
||||
}
|
||||
tmp = carry;
|
||||
MP_SUB_BORROW(r0a, r3b, r0a, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
tmp -= carry;
|
||||
}
|
||||
r3b = tmp;
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
mp_digit maxInt = MP_DIGIT_MAX;
|
||||
MP_ADD_CARRY (r0a, 1, r0a, 0, carry);
|
||||
MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
|
||||
MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
|
||||
MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
|
||||
&& (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
|
||||
((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0a, 1, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
r1b = r2a = r2b = r3a = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 7;
|
||||
MP_DIGIT(r, 6) = r3a;
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
#else
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
a6b = a6 >> 32;
|
||||
a6a_a5b = a6 << 32;
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
a5b = a5 >> 32;
|
||||
a6a_a5b |= a5b;
|
||||
a5b = a5b << 32;
|
||||
a5a_a4b = a5 << 32;
|
||||
a5a = a5 & 0xffffffff;
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
a5a_a4b |= a4 >> 32;
|
||||
a4a_a3b = a4 << 32;
|
||||
case 4:
|
||||
a3b = MP_DIGIT(a, 3) >> 32;
|
||||
a4a_a3b |= a3b;
|
||||
a3b = a3b << 32;
|
||||
}
|
||||
|
||||
r3 = MP_DIGIT(a, 3) & 0xffffffff;
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1, a3b, r1, 0, carry);
|
||||
MP_ADD_CARRY (r2, a4 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, a5a, r3, carry, carry);
|
||||
MP_ADD_CARRY (r1, a5b, r1, 0, carry);
|
||||
MP_ADD_CARRY (r2, a6 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, 0, r3, carry, carry);
|
||||
|
||||
MP_SUB_BORROW(r0, a4a_a3b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6b , r3, carry, carry);
|
||||
MP_SUB_BORROW(r0, a6a_a5b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6b , r1, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
|
||||
|
||||
/* if the value is negative, r3 has a 2's complement
|
||||
* high value */
|
||||
r3b = (int)(r3 >>32);
|
||||
while (r3b > 0) {
|
||||
r3 &= 0xffffffff;
|
||||
MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, 0, r3, carry, carry);
|
||||
}
|
||||
MP_SUB_BORROW(r0, r3b, r0, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
MP_ADD_CARRY (r0, 1, r0, 0, carry);
|
||||
MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
|
||||
MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
|
||||
&& ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
|
||||
((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
r2 = r3 = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 4));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
MP_DIGIT(r, 3) = r3;
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p224. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p224.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p224.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p224. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp224(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P224) {
|
||||
group->meth->field_mod = &ec_GFp_nistp224_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp224_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp224_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp224_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r.
|
||||
* Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
mp_digit carry;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a8=0, a9=0, a10=0, a11=0, a12=0, a13=0, a14=0, a15=0;
|
||||
mp_digit r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
int r8; /* must be a signed value ! */
|
||||
#else
|
||||
mp_digit a4=0, a5=0, a6=0, a7=0;
|
||||
mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
int r4; /* must be a signed value ! */
|
||||
#endif
|
||||
/* for polynomials larger than twice the field size
|
||||
* use regular reduction */
|
||||
if (a_bits < 256) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a,r);
|
||||
}
|
||||
if (a_bits > 512) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
switch (a_used) {
|
||||
case 16:
|
||||
a15 = MP_DIGIT(a,15);
|
||||
case 15:
|
||||
a14 = MP_DIGIT(a,14);
|
||||
case 14:
|
||||
a13 = MP_DIGIT(a,13);
|
||||
case 13:
|
||||
a12 = MP_DIGIT(a,12);
|
||||
case 12:
|
||||
a11 = MP_DIGIT(a,11);
|
||||
case 11:
|
||||
a10 = MP_DIGIT(a,10);
|
||||
case 10:
|
||||
a9 = MP_DIGIT(a,9);
|
||||
case 9:
|
||||
a8 = MP_DIGIT(a,8);
|
||||
}
|
||||
|
||||
r0 = MP_DIGIT(a,0);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r4 = MP_DIGIT(a,4);
|
||||
r5 = MP_DIGIT(a,5);
|
||||
r6 = MP_DIGIT(a,6);
|
||||
r7 = MP_DIGIT(a,7);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 = carry;
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r3, a12, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* combine last bottom of sum 3 with second sum 2 */
|
||||
MP_ADD_CARRY(r0, a8, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a9, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a10, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a12, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry); /* from sum 3 */
|
||||
r8 += carry;
|
||||
/* sum 3 (rest of it)*/
|
||||
MP_ADD_CARRY(r6, a14, r6, 0, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 4 (rest of it)*/
|
||||
MP_ADD_CARRY(r0, a9, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a10, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a11, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a13, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a14, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a15, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a13, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a8, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a11, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a12, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a13, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a8, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a10, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a12, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a13, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a14, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a15, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a9, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a11, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a13, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a14, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a15, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a8, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a9, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a10, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a12, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a14, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a15, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a9, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a10, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a11, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a13, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r8 > 0) {
|
||||
mp_digit r8_d = r8;
|
||||
MP_ADD_CARRY(r0, r8_d, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 0, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, -r8_d, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r8 < 0) {
|
||||
mp_digit r8_d = -r8;
|
||||
MP_SUB_BORROW(r0, r8_d, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, -r8_d, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = -carry;
|
||||
}
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,8));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 8;
|
||||
|
||||
MP_DIGIT(r,7) = r7;
|
||||
MP_DIGIT(r,6) = r6;
|
||||
MP_DIGIT(r,5) = r5;
|
||||
MP_DIGIT(r,4) = r4;
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r7 == MP_DIGIT_MAX) &&
|
||||
((r6 > 1) || ((r6 == 1) &&
|
||||
(r5 || r4 || r3 ||
|
||||
((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX)
|
||||
&& (r0 == MP_DIGIT_MAX)))))) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
#ifdef notdef
|
||||
|
||||
|
||||
/* smooth the negatives */
|
||||
while (MP_SIGN(r) != MP_ZPOS) {
|
||||
MP_CHECKOK(mp_add(r, &meth->irr, r));
|
||||
}
|
||||
while (MP_USED(r) > 8) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
/* final reduction if necessary */
|
||||
if (MP_DIGIT(r,7) >= MP_DIGIT(&meth->irr,7)) {
|
||||
if (mp_cmp(r,&meth->irr) != MP_LT) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a,7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a,6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a,5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a,4);
|
||||
}
|
||||
a7l = a7 << 32;
|
||||
a7h = a7 >> 32;
|
||||
a6l = a6 << 32;
|
||||
a6h = a6 >> 32;
|
||||
a5l = a5 << 32;
|
||||
a5h = a5 >> 32;
|
||||
a4l = a4 << 32;
|
||||
a4h = a4 >> 32;
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r0 = MP_DIGIT(a,0);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 = carry;
|
||||
MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r1, a6l, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
MP_ADD_CARRY(r1, a6l, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
|
||||
/* sum 3 */
|
||||
MP_ADD_CARRY(r0, a4, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5l >> 32, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 4 */
|
||||
MP_ADD_CARRY(r0, a4h | a5l, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a7, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a6h | a4l, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a5h | a6l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6h, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, (a4l>>32)|a5l,r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a6, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a4h|(a5h<<32),r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a6h|a7l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7h|a4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a4h|a5l, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6l, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a7, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a4h<<32, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a5, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6h<<32, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r4 > 0) {
|
||||
mp_digit r4_long = r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_ADD_CARRY(r0, r4_long, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, -r4l, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r4 < 0) {
|
||||
mp_digit r4_long = -r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_SUB_BORROW(r0, r4_long, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, -r4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = -carry;
|
||||
}
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,4));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r3 > 0xFFFFFFFF00000001ULL) ||
|
||||
((r3 == 0xFFFFFFFF00000001ULL) &&
|
||||
(r2 || (r1 >> 32)||
|
||||
(r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) {
|
||||
/* very rare, just use mp_sub */
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p256. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p256.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp256_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p256.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p256. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp256(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P256) {
|
||||
group->meth->field_mod = &ec_GFp_nistp256_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp256_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp256_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r.
|
||||
* Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m[10];
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit s[10][12];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 12;
|
||||
MP_USED(&m[i]) = 12;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#else
|
||||
mp_digit s[10][6];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 6;
|
||||
MP_USED(&m[i]) = 6;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = 0;
|
||||
s[1][3] = 0;
|
||||
s[1][4] = MP_DIGIT(a, 21);
|
||||
s[1][5] = MP_DIGIT(a, 22);
|
||||
s[1][6] = MP_DIGIT(a, 23);
|
||||
s[1][7] = 0;
|
||||
s[1][8] = 0;
|
||||
s[1][9] = 0;
|
||||
s[1][10] = 0;
|
||||
s[1][11] = 0;
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+12);
|
||||
}
|
||||
s[3][0] = MP_DIGIT(a, 21);
|
||||
s[3][1] = MP_DIGIT(a, 22);
|
||||
s[3][2] = MP_DIGIT(a, 23);
|
||||
for (i = 3; i < 12; i++) {
|
||||
s[3][i] = MP_DIGIT(a, i+9);
|
||||
}
|
||||
s[4][0] = 0;
|
||||
s[4][1] = MP_DIGIT(a, 23);
|
||||
s[4][2] = 0;
|
||||
s[4][3] = MP_DIGIT(a, 20);
|
||||
for (i = 4; i < 12; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+8);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = 0;
|
||||
s[5][3] = 0;
|
||||
s[5][4] = MP_DIGIT(a, 20);
|
||||
s[5][5] = MP_DIGIT(a, 21);
|
||||
s[5][6] = MP_DIGIT(a, 22);
|
||||
s[5][7] = MP_DIGIT(a, 23);
|
||||
s[5][8] = 0;
|
||||
s[5][9] = 0;
|
||||
s[5][10] = 0;
|
||||
s[5][11] = 0;
|
||||
s[6][0] = MP_DIGIT(a, 20);
|
||||
s[6][1] = 0;
|
||||
s[6][2] = 0;
|
||||
s[6][3] = MP_DIGIT(a, 21);
|
||||
s[6][4] = MP_DIGIT(a, 22);
|
||||
s[6][5] = MP_DIGIT(a, 23);
|
||||
s[6][6] = 0;
|
||||
s[6][7] = 0;
|
||||
s[6][8] = 0;
|
||||
s[6][9] = 0;
|
||||
s[6][10] = 0;
|
||||
s[6][11] = 0;
|
||||
s[7][0] = MP_DIGIT(a, 23);
|
||||
for (i = 1; i < 12; i++) {
|
||||
s[7][i] = MP_DIGIT(a, i+11);
|
||||
}
|
||||
s[8][0] = 0;
|
||||
s[8][1] = MP_DIGIT(a, 20);
|
||||
s[8][2] = MP_DIGIT(a, 21);
|
||||
s[8][3] = MP_DIGIT(a, 22);
|
||||
s[8][4] = MP_DIGIT(a, 23);
|
||||
s[8][5] = 0;
|
||||
s[8][6] = 0;
|
||||
s[8][7] = 0;
|
||||
s[8][8] = 0;
|
||||
s[8][9] = 0;
|
||||
s[8][10] = 0;
|
||||
s[8][11] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = 0;
|
||||
s[9][2] = 0;
|
||||
s[9][3] = MP_DIGIT(a, 23);
|
||||
s[9][4] = MP_DIGIT(a, 23);
|
||||
s[9][5] = 0;
|
||||
s[9][6] = 0;
|
||||
s[9][7] = 0;
|
||||
s[9][8] = 0;
|
||||
s[9][9] = 0;
|
||||
s[9][10] = 0;
|
||||
s[9][11] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#else
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[1][3] = MP_DIGIT(a, 11) >> 32;
|
||||
s[1][4] = 0;
|
||||
s[1][5] = 0;
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+6);
|
||||
}
|
||||
s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32);
|
||||
}
|
||||
s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[4][1] = MP_DIGIT(a, 10) << 32;
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+4);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = MP_DIGIT(a, 10);
|
||||
s[5][3] = MP_DIGIT(a, 11);
|
||||
s[5][4] = 0;
|
||||
s[5][5] = 0;
|
||||
s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32;
|
||||
s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32;
|
||||
s[6][2] = MP_DIGIT(a, 11);
|
||||
s[6][3] = 0;
|
||||
s[6][4] = 0;
|
||||
s[6][5] = 0;
|
||||
s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 1; i < 6; i++) {
|
||||
s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32);
|
||||
}
|
||||
s[8][0] = MP_DIGIT(a, 10) << 32;
|
||||
s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[8][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[8][3] = 0;
|
||||
s[8][4] = 0;
|
||||
s[8][5] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[9][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[9][3] = 0;
|
||||
s[9][4] = 0;
|
||||
s[9][5] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p384. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p384.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p384.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p384. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp384(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P384) {
|
||||
group->meth->field_mod = &ec_GFp_nistp384_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp384_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp384_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP521_DIGITS ECL_CURVE_DIGITS(521)
|
||||
|
||||
/* Fast modular reduction for p521 = 2^521 - 1. a can be r. Uses
|
||||
* algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m1;
|
||||
|
||||
mp_digit s1[ECP521_DIGITS] = { 0 };
|
||||
|
||||
MP_SIGN(&m1) = MP_ZPOS;
|
||||
MP_ALLOC(&m1) = ECP521_DIGITS;
|
||||
MP_USED(&m1) = ECP521_DIGITS;
|
||||
MP_DIGITS(&m1) = s1;
|
||||
|
||||
if (a_bits < 521) {
|
||||
if (a==r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if (a_bits > (521*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#define FIRST_DIGIT (ECP521_DIGITS-1)
|
||||
for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) {
|
||||
s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9)
|
||||
| (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9));
|
||||
}
|
||||
s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9;
|
||||
|
||||
if ( a != r ) {
|
||||
MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS));
|
||||
for (i = 0; i < ECP521_DIGITS; i++) {
|
||||
MP_DIGIT(r,i) = MP_DIGIT(a, i);
|
||||
}
|
||||
}
|
||||
MP_USED(r) = ECP521_DIGITS;
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
|
||||
MP_CHECKOK(s_mp_add(r, &m1));
|
||||
if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) {
|
||||
MP_CHECKOK(s_mp_add_d(r,1));
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
}
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p521. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p521.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p521.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p521. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp521(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P521) {
|
||||
group->meth->field_mod = &ec_GFp_nistp521_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp521_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp521_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp521_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. Assumes input
|
||||
* is already field-encoded using field_enc, and returns output that is
|
||||
* still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, temp, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&temp) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda));
|
||||
MP_CHECKOK(mp_init(&temp));
|
||||
MP_CHECKOK(mp_init(&tempx));
|
||||
MP_CHECKOK(mp_init(&tempy));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py-qy) / (px-qx) */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qy = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = (3qx^2+a) / (2qy) */
|
||||
MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 3));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempx, &temp, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 2));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempx, &tempy, &lambda, group->meth));
|
||||
}
|
||||
/* rx = lambda^2 - px - qx */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
|
||||
/* ry = (x1-x2) * lambda - y1 */
|
||||
MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
MP_CHECKOK(mp_copy(&tempy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&temp);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy));
|
||||
/* nqy = -qy */
|
||||
MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth));
|
||||
res = group->point_add(px, py, qx, &nqy, rx, ry, group);
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err
|
||||
ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl));
|
||||
MP_CHECKOK(mp_init(&accr));
|
||||
MP_CHECKOK(mp_init(&tmp));
|
||||
MP_CHECKOK(mp_init(&pxt));
|
||||
MP_CHECKOK(mp_init(&pyt));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
|
||||
if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
||||
@@ -1,568 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves
|
||||
* using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Performs tidying on a short multi-precision floating point integer (the
|
||||
* lower group->numDoubles floats). */
|
||||
void
|
||||
ecfp_tidyShort(double *t, const EC_group_fp * group)
|
||||
{
|
||||
group->ecfp_tidy(t, group->alpha, group);
|
||||
}
|
||||
|
||||
/* Performs tidying on only the upper float digits of a multi-precision
|
||||
* floating point integer, i.e. the digits beyond the regular length which
|
||||
* are removed in the reduction step. */
|
||||
void
|
||||
ecfp_tidyUpper(double *t, const EC_group_fp * group)
|
||||
{
|
||||
group->ecfp_tidy(t + group->numDoubles,
|
||||
group->alpha + group->numDoubles, group);
|
||||
}
|
||||
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of the
|
||||
* doubles is reduced to the regular precision group->doubleBitSize. This
|
||||
* might result in some float digits being negative. Alternative C version
|
||||
* for portability. */
|
||||
void
|
||||
ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
int i;
|
||||
|
||||
/* Do carrying */
|
||||
for (i = 0; i < group->numDoubles - 1; i++) {
|
||||
q = t[i] + alpha[i + 1];
|
||||
q -= alpha[i + 1];
|
||||
t[i] -= q;
|
||||
t[i + 1] += q;
|
||||
|
||||
/* If we don't assume that truncation rounding is used, then q
|
||||
* might be 2^n bigger than expected (if it rounds up), then t[0]
|
||||
* could be negative and t[1] 2^n larger than expected. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Performs a more mathematically precise "tidying" so that each term is
|
||||
* positive. This is slower than the regular tidying, and is used for
|
||||
* conversion from floating point to integer. */
|
||||
void
|
||||
ecfp_positiveTidy(double *t, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
int i;
|
||||
|
||||
/* Do carrying */
|
||||
for (i = 0; i < group->numDoubles - 1; i++) {
|
||||
/* Subtract beta to force rounding down */
|
||||
q = t[i] - ecfp_beta[i + 1];
|
||||
q += group->alpha[i + 1];
|
||||
q -= group->alpha[i + 1];
|
||||
t[i] -= q;
|
||||
t[i + 1] += q;
|
||||
|
||||
/* Due to subtracting ecfp_beta, we should have each term a
|
||||
* non-negative int */
|
||||
ECFP_ASSERT(t[i] / ecfp_exp[i] ==
|
||||
(unsigned long long) (t[i] / ecfp_exp[i]));
|
||||
ECFP_ASSERT(t[i] >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Converts from a floating point representation into an mp_int. Expects
|
||||
* that d is already reduced. */
|
||||
void
|
||||
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup)
|
||||
{
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
unsigned short i16[(group->primeBitSize + 15) / 16];
|
||||
double q = 1;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* TEST uint32_t z = 0; */
|
||||
unsigned int z = 0;
|
||||
#else
|
||||
uint64_t z = 0;
|
||||
#endif
|
||||
int zBits = 0;
|
||||
int copiedBits = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
mp_digit *out;
|
||||
|
||||
/* Result should always be >= 0, so set sign accordingly */
|
||||
MP_SIGN(mpout) = MP_ZPOS;
|
||||
|
||||
/* Tidy up so we're just dealing with positive numbers */
|
||||
ecfp_positiveTidy(d, group);
|
||||
|
||||
/* We might need to do this reduction step more than once if the
|
||||
* reduction adds smaller terms which carry-over to cause another
|
||||
* reduction. However, this should happen very rarely, if ever,
|
||||
* depending on the elliptic curve. */
|
||||
do {
|
||||
/* Init loop data */
|
||||
z = 0;
|
||||
zBits = 0;
|
||||
q = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
copiedBits = 0;
|
||||
|
||||
/* Might have to do a bit more reduction */
|
||||
group->ecfp_singleReduce(d, group);
|
||||
|
||||
/* Grow the size of the mpint if it's too small */
|
||||
s_mp_grow(mpout, group->numInts);
|
||||
MP_USED(mpout) = group->numInts;
|
||||
out = MP_DIGITS(mpout);
|
||||
|
||||
/* Convert double to 16 bit integers */
|
||||
while (copiedBits < group->primeBitSize) {
|
||||
if (zBits < 16) {
|
||||
z += d[i] * q;
|
||||
i++;
|
||||
ECFP_ASSERT(i < (group->primeBitSize + 15) / 16);
|
||||
zBits += group->doubleBitSize;
|
||||
}
|
||||
i16[j] = z;
|
||||
j++;
|
||||
z >>= 16;
|
||||
zBits -= 16;
|
||||
q *= ecfp_twom16;
|
||||
copiedBits += 16;
|
||||
}
|
||||
} while (z != 0);
|
||||
|
||||
/* Convert 16 bit integers to mp_digit */
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
for (i = 0; i < (group->primeBitSize + 15) / 16; i += 2) {
|
||||
*out = 0;
|
||||
if (i + 1 < (group->primeBitSize + 15) / 16) {
|
||||
*out = i16[i + 1];
|
||||
*out <<= 16;
|
||||
}
|
||||
*out++ += i16[i];
|
||||
}
|
||||
#else /* 64 bit */
|
||||
for (i = 0; i < (group->primeBitSize + 15) / 16; i += 4) {
|
||||
*out = 0;
|
||||
if (i + 3 < (group->primeBitSize + 15) / 16) {
|
||||
*out = i16[i + 3];
|
||||
*out <<= 16;
|
||||
}
|
||||
if (i + 2 < (group->primeBitSize + 15) / 16) {
|
||||
*out += i16[i + 2];
|
||||
*out <<= 16;
|
||||
}
|
||||
if (i + 1 < (group->primeBitSize + 15) / 16) {
|
||||
*out += i16[i + 1];
|
||||
*out <<= 16;
|
||||
}
|
||||
*out++ += i16[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Perform final reduction. mpout should already be the same number
|
||||
* of bits as p, but might not be less than p. Make it so. Since
|
||||
* mpout has the same number of bits as p, and 2p has a larger bit
|
||||
* size, then mpout < 2p, so a single subtraction of p will suffice. */
|
||||
if (mp_cmp(mpout, &ecgroup->meth->irr) >= 0) {
|
||||
mp_sub(mpout, &ecgroup->meth->irr, mpout);
|
||||
}
|
||||
|
||||
/* Shrink the size of the mp_int to the actual used size (required for
|
||||
* mp_cmp_z == 0) */
|
||||
out = MP_DIGITS(mpout);
|
||||
for (i = group->numInts - 1; i > 0; i--) {
|
||||
if (out[i] != 0)
|
||||
break;
|
||||
}
|
||||
MP_USED(mpout) = i + 1;
|
||||
|
||||
/* Should be between 0 and p-1 */
|
||||
ECFP_ASSERT(mp_cmp(mpout, &ecgroup->meth->irr) < 0);
|
||||
ECFP_ASSERT(mp_cmp_z(mpout) >= 0);
|
||||
}
|
||||
|
||||
/* Converts from an mpint into a floating point representation. */
|
||||
void
|
||||
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup)
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
int size;
|
||||
double shift = 1;
|
||||
mp_digit *in;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
/* if debug mode, convert result back using ecfp_fp2i into cmp, then
|
||||
* compare to x. */
|
||||
mp_int cmp;
|
||||
|
||||
MP_DIGITS(&cmp) = NULL;
|
||||
mp_init(&cmp);
|
||||
#endif
|
||||
|
||||
ECFP_ASSERT(group != NULL);
|
||||
|
||||
/* init output to 0 (since we skip over some terms) */
|
||||
for (i = 0; i < group->numDoubles; i++)
|
||||
out[i] = 0;
|
||||
i = 0;
|
||||
|
||||
size = MP_USED(x);
|
||||
in = MP_DIGITS(x);
|
||||
|
||||
/* Copy from int into doubles */
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
while (j < size) {
|
||||
while (group->doubleBitSize * (i + 1) <= 32 * j) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(group->doubleBitSize * i <= 32 * j);
|
||||
out[i] = in[j];
|
||||
out[i] *= shift;
|
||||
shift *= ecfp_two32;
|
||||
j++;
|
||||
}
|
||||
#else
|
||||
while (j < size) {
|
||||
while (group->doubleBitSize * (i + 1) <= 64 * j) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(group->doubleBitSize * i <= 64 * j);
|
||||
out[i] = (in[j] & 0x00000000FFFFFFFF) * shift;
|
||||
|
||||
while (group->doubleBitSize * (i + 1) <= 64 * j + 32) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(24 * i <= 64 * j + 32);
|
||||
out[i] = (in[j] & 0xFFFFFFFF00000000) * shift;
|
||||
|
||||
shift *= ecfp_two64;
|
||||
j++;
|
||||
}
|
||||
#endif
|
||||
/* Realign bits to match double boundaries */
|
||||
ecfp_tidyShort(out, group);
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
/* Convert result back to mp_int, compare to original */
|
||||
ecfp_fp2i(&cmp, out, ecgroup);
|
||||
ECFP_ASSERT(mp_cmp(&cmp, x) == 0);
|
||||
mp_clear(&cmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses Jacobian coordinates. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ecfp_jac_pt precomp[16], r;
|
||||
ecfp_aff_pt p;
|
||||
EC_group_fp *group;
|
||||
|
||||
mp_int rz;
|
||||
int i, ni, d;
|
||||
|
||||
ARGCHK(ecgroup != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
group = (EC_group_fp *) ecgroup->extra1;
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
|
||||
/* init p, da */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||||
|
||||
/* Do precomputation */
|
||||
group->precompute_jac(precomp, &p, group);
|
||||
|
||||
/* Do main body of calculations */
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
|
||||
/* R = 2^4 * R */
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
|
||||
/* R = R + (ni * P) */
|
||||
group->pt_add_jac(&r, &precomp[ni], &r, group);
|
||||
}
|
||||
|
||||
/* Convert back to integer */
|
||||
ecfp_fp2i(rx, r.x, ecgroup);
|
||||
ecfp_fp2i(ry, r.y, ecgroup);
|
||||
ecfp_fp2i(&rz, r.z, ecgroup);
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Uses mixed Jacobian-affine coordinates to perform a point
|
||||
* multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
|
||||
* coordinates (Jacobian coordinates for doubles and affine coordinates
|
||||
* for additions; based on recommendation from Brown et al.). Not very
|
||||
* time efficient but quite space efficient, no precomputation needed.
|
||||
* group contains the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Performs calculations in floating point number format, since
|
||||
* this is faster than the integer operations on the ULTRASPARC III.
|
||||
* Uses left-to-right binary method (double & add) (algorithm 9) for
|
||||
* scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res;
|
||||
mp_int sx, sy, sz;
|
||||
|
||||
ecfp_aff_pt p;
|
||||
ecfp_jac_pt r;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
|
||||
int i, l;
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
MP_CHECKOK(mp_init(&sz));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
res = MP_RANGE;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Convert from integer to floating point */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||||
|
||||
/* Init r to point at infinity */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
/* double and add method */
|
||||
l = mpl_significant_bits(n) - 1;
|
||||
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
|
||||
/* if n_i = 1, then R = R + Q */
|
||||
if (MP_GET_BIT(n, i) != 0) {
|
||||
group->pt_add_jac_aff(&r, &p, &r, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from floating point to integer */
|
||||
ecfp_fp2i(&sx, r.x, ecgroup);
|
||||
ecfp_fp2i(&sy, r.y, ecgroup);
|
||||
ecfp_fp2i(&sz, r.z, ecgroup);
|
||||
|
||||
/* convert result R to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point
|
||||
* multiplication from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy, sz;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
ecfp_chud_pt precomp[16];
|
||||
|
||||
ecfp_aff_pt p;
|
||||
ecfp_jm_pt r;
|
||||
|
||||
signed char naf[group->orderBitSize + 1];
|
||||
int i;
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
MP_CHECKOK(mp_init(&sz));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
res = MP_RANGE;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Convert from integer to floating point */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||||
|
||||
/* Perform precomputation */
|
||||
group->precompute_chud(precomp, &p, group);
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, group->orderBitSize, n, 5);
|
||||
|
||||
/* Init R = pt at infinity */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
/* wNAF method */
|
||||
for (i = group->orderBitSize; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
group->pt_dbl_jm(&r, &r, group);
|
||||
|
||||
if (naf[i] != 0) {
|
||||
group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r,
|
||||
group);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from floating point to integer */
|
||||
ecfp_fp2i(&sx, r.x, ecgroup);
|
||||
ecfp_fp2i(&sy, r.y, ecgroup);
|
||||
ecfp_fp2i(&sz, r.z, ecgroup);
|
||||
|
||||
/* convert result R to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Cleans up extra memory allocated in ECGroup for this implementation. */
|
||||
void
|
||||
ec_GFp_extra_free_fp(ECGroup *group)
|
||||
{
|
||||
if (group->extra1 != NULL) {
|
||||
free(group->extra1);
|
||||
group->extra1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tests what precision floating point arithmetic is set to. This should
|
||||
* be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
|
||||
* (extended precision on x86) and sets it into the EC_group_fp. Returns
|
||||
* either 53 or 64 accordingly. */
|
||||
int
|
||||
ec_set_fp_precision(EC_group_fp * group)
|
||||
{
|
||||
double a = 9007199254740992.0; /* 2^53 */
|
||||
double b = a + 1;
|
||||
|
||||
if (a == b) {
|
||||
group->fpPrecision = 53;
|
||||
group->alpha = ecfp_alpha_53;
|
||||
return 53;
|
||||
}
|
||||
group->fpPrecision = 64;
|
||||
group->alpha = ecfp_alpha_64;
|
||||
return 64;
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecp_fp_h_
|
||||
#define __ecp_fp_h_
|
||||
|
||||
#include "mpi.h"
|
||||
#include "ecl.h"
|
||||
#include "ecp.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "mpi-priv.h"
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Largest number of doubles to store one reduced number in floating
|
||||
* point. Used for memory allocation on the stack. */
|
||||
#define ECFP_MAXDOUBLES 10
|
||||
|
||||
/* For debugging purposes */
|
||||
#ifndef ECL_DEBUG
|
||||
#define ECFP_ASSERT(x)
|
||||
#else
|
||||
#define ECFP_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
/* ECFP_Ti = 2^(i*24) Define as preprocessor constants so we can use in
|
||||
* multiple static constants */
|
||||
#define ECFP_T0 1.0
|
||||
#define ECFP_T1 16777216.0
|
||||
#define ECFP_T2 281474976710656.0
|
||||
#define ECFP_T3 4722366482869645213696.0
|
||||
#define ECFP_T4 79228162514264337593543950336.0
|
||||
#define ECFP_T5 1329227995784915872903807060280344576.0
|
||||
#define ECFP_T6 22300745198530623141535718272648361505980416.0
|
||||
#define ECFP_T7 374144419156711147060143317175368453031918731001856.0
|
||||
#define ECFP_T8 6277101735386680763835789423207666416102355444464034512896.0
|
||||
#define ECFP_T9 105312291668557186697918027683670432318895095400549111254310977536.0
|
||||
#define ECFP_T10 1766847064778384329583297500742918515827483896875618958121606201292619776.0
|
||||
#define ECFP_T11 29642774844752946028434172162224104410437116074403984394101141506025761187823616.0
|
||||
#define ECFP_T12 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056.0
|
||||
#define ECFP_T13 8343699359066055009355553539724812947666814540455674882605631280555545803830627148527195652096.0
|
||||
#define ECFP_T14 139984046386112763159840142535527767382602843577165595931249318810236991948760059086304843329475444736.0
|
||||
#define ECFP_T15 2348542582773833227889480596789337027375682548908319870707290971532209025114608443463698998384768703031934976.0
|
||||
#define ECFP_T16 39402006196394479212279040100143613805079739270465446667948293404245\
|
||||
721771497210611414266254884915640806627990306816.0
|
||||
#define ECFP_T17 66105596879024859895191530803277103982840468296428121928464879527440\
|
||||
5791236311345825189210439715284847591212025023358304256.0
|
||||
#define ECFP_T18 11090678776483259438313656736572334813745748301503266300681918322458\
|
||||
485231222502492159897624416558312389564843845614287315896631296.0
|
||||
#define ECFP_T19 18607071341967536398062689481932916079453218833595342343206149099024\
|
||||
36577570298683715049089827234727835552055312041415509848580169253519\
|
||||
36.0
|
||||
|
||||
#define ECFP_TWO160 1461501637330902918203684832716283019655932542976.0
|
||||
#define ECFP_TWO192 6277101735386680763835789423207666416102355444464034512896.0
|
||||
#define ECFP_TWO224 26959946667150639794667015087019630673637144422540572481103610249216.0
|
||||
|
||||
/* Multiplicative constants */
|
||||
static const double ecfp_two32 = 4294967296.0;
|
||||
static const double ecfp_two64 = 18446744073709551616.0;
|
||||
static const double ecfp_twom16 = .0000152587890625;
|
||||
static const double ecfp_twom128 =
|
||||
.00000000000000000000000000000000000000293873587705571876992184134305561419454666389193021880377187926569604314863681793212890625;
|
||||
static const double ecfp_twom129 =
|
||||
.000000000000000000000000000000000000001469367938527859384960920671527807097273331945965109401885939632848021574318408966064453125;
|
||||
static const double ecfp_twom160 =
|
||||
.0000000000000000000000000000000000000000000000006842277657836020854119773355907793609766904013068924666782559979930620520927053718196475529111921787261962890625;
|
||||
static const double ecfp_twom192 =
|
||||
.000000000000000000000000000000000000000000000000000000000159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625;
|
||||
static const double ecfp_twom224 =
|
||||
.00000000000000000000000000000000000000000000000000000000000000000003709206150687421385731735261547639513367564778757791002453039058917581340095629358997312082723208437536338919136001159027049567384892725385725498199462890625;
|
||||
|
||||
/* ecfp_exp[i] = 2^(i*ECFP_DSIZE) */
|
||||
static const double ecfp_exp[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_T0, ECFP_T1, ECFP_T2, ECFP_T3, ECFP_T4, ECFP_T5,
|
||||
ECFP_T6, ECFP_T7, ECFP_T8, ECFP_T9, ECFP_T10, ECFP_T11,
|
||||
ECFP_T12, ECFP_T13, ECFP_T14, ECFP_T15, ECFP_T16, ECFP_T17, ECFP_T18,
|
||||
ECFP_T19
|
||||
};
|
||||
|
||||
/* 1.1 * 2^52 Uses 2^52 to truncate, the .1 is an extra 2^51 to protect
|
||||
* the 2^52 bit, so that adding alphas to a negative number won't borrow
|
||||
* and empty the important 2^52 bit */
|
||||
#define ECFP_ALPHABASE_53 6755399441055744.0
|
||||
/* Special case: On some platforms, notably x86 Linux, there is an
|
||||
* extended-precision floating point representation with 64-bits of
|
||||
* precision in the mantissa. These extra bits of precision require a
|
||||
* larger value of alpha to truncate, i.e. 1.1 * 2^63. */
|
||||
#define ECFP_ALPHABASE_64 13835058055282163712.0
|
||||
|
||||
/*
|
||||
* ecfp_alpha[i] = 1.5 * 2^(52 + i*ECFP_DSIZE) we add and subtract alpha
|
||||
* to truncate floating point numbers to a certain number of bits for
|
||||
* tidying */
|
||||
static const double ecfp_alpha_53[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_ALPHABASE_53 * ECFP_T0,
|
||||
ECFP_ALPHABASE_53 * ECFP_T1,
|
||||
ECFP_ALPHABASE_53 * ECFP_T2,
|
||||
ECFP_ALPHABASE_53 * ECFP_T3,
|
||||
ECFP_ALPHABASE_53 * ECFP_T4,
|
||||
ECFP_ALPHABASE_53 * ECFP_T5,
|
||||
ECFP_ALPHABASE_53 * ECFP_T6,
|
||||
ECFP_ALPHABASE_53 * ECFP_T7,
|
||||
ECFP_ALPHABASE_53 * ECFP_T8,
|
||||
ECFP_ALPHABASE_53 * ECFP_T9,
|
||||
ECFP_ALPHABASE_53 * ECFP_T10,
|
||||
ECFP_ALPHABASE_53 * ECFP_T11,
|
||||
ECFP_ALPHABASE_53 * ECFP_T12,
|
||||
ECFP_ALPHABASE_53 * ECFP_T13,
|
||||
ECFP_ALPHABASE_53 * ECFP_T14,
|
||||
ECFP_ALPHABASE_53 * ECFP_T15,
|
||||
ECFP_ALPHABASE_53 * ECFP_T16,
|
||||
ECFP_ALPHABASE_53 * ECFP_T17,
|
||||
ECFP_ALPHABASE_53 * ECFP_T18,
|
||||
ECFP_ALPHABASE_53 * ECFP_T19
|
||||
};
|
||||
|
||||
/*
|
||||
* ecfp_alpha[i] = 1.5 * 2^(63 + i*ECFP_DSIZE) we add and subtract alpha
|
||||
* to truncate floating point numbers to a certain number of bits for
|
||||
* tidying */
|
||||
static const double ecfp_alpha_64[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_ALPHABASE_64 * ECFP_T0,
|
||||
ECFP_ALPHABASE_64 * ECFP_T1,
|
||||
ECFP_ALPHABASE_64 * ECFP_T2,
|
||||
ECFP_ALPHABASE_64 * ECFP_T3,
|
||||
ECFP_ALPHABASE_64 * ECFP_T4,
|
||||
ECFP_ALPHABASE_64 * ECFP_T5,
|
||||
ECFP_ALPHABASE_64 * ECFP_T6,
|
||||
ECFP_ALPHABASE_64 * ECFP_T7,
|
||||
ECFP_ALPHABASE_64 * ECFP_T8,
|
||||
ECFP_ALPHABASE_64 * ECFP_T9,
|
||||
ECFP_ALPHABASE_64 * ECFP_T10,
|
||||
ECFP_ALPHABASE_64 * ECFP_T11,
|
||||
ECFP_ALPHABASE_64 * ECFP_T12,
|
||||
ECFP_ALPHABASE_64 * ECFP_T13,
|
||||
ECFP_ALPHABASE_64 * ECFP_T14,
|
||||
ECFP_ALPHABASE_64 * ECFP_T15,
|
||||
ECFP_ALPHABASE_64 * ECFP_T16,
|
||||
ECFP_ALPHABASE_64 * ECFP_T17,
|
||||
ECFP_ALPHABASE_64 * ECFP_T18,
|
||||
ECFP_ALPHABASE_64 * ECFP_T19
|
||||
};
|
||||
|
||||
/* 0.011111111111111111111111 (binary) = 0.5 - 2^25 (24 ones) */
|
||||
#define ECFP_BETABASE 0.4999999701976776123046875
|
||||
|
||||
/*
|
||||
* We subtract beta prior to using alpha to simulate rounding down. We
|
||||
* make this close to 0.5 to round almost everything down, but exactly 0.5
|
||||
* would cause some incorrect rounding. */
|
||||
static const double ecfp_beta[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_BETABASE * ECFP_T0,
|
||||
ECFP_BETABASE * ECFP_T1,
|
||||
ECFP_BETABASE * ECFP_T2,
|
||||
ECFP_BETABASE * ECFP_T3,
|
||||
ECFP_BETABASE * ECFP_T4,
|
||||
ECFP_BETABASE * ECFP_T5,
|
||||
ECFP_BETABASE * ECFP_T6,
|
||||
ECFP_BETABASE * ECFP_T7,
|
||||
ECFP_BETABASE * ECFP_T8,
|
||||
ECFP_BETABASE * ECFP_T9,
|
||||
ECFP_BETABASE * ECFP_T10,
|
||||
ECFP_BETABASE * ECFP_T11,
|
||||
ECFP_BETABASE * ECFP_T12,
|
||||
ECFP_BETABASE * ECFP_T13,
|
||||
ECFP_BETABASE * ECFP_T14,
|
||||
ECFP_BETABASE * ECFP_T15,
|
||||
ECFP_BETABASE * ECFP_T16,
|
||||
ECFP_BETABASE * ECFP_T17,
|
||||
ECFP_BETABASE * ECFP_T18,
|
||||
ECFP_BETABASE * ECFP_T19
|
||||
};
|
||||
|
||||
static const double ecfp_beta_160 = ECFP_BETABASE * ECFP_TWO160;
|
||||
static const double ecfp_beta_192 = ECFP_BETABASE * ECFP_TWO192;
|
||||
static const double ecfp_beta_224 = ECFP_BETABASE * ECFP_TWO224;
|
||||
|
||||
/* Affine EC Point. This is the basic representation (x, y) of an elliptic
|
||||
* curve point. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
} ecfp_aff_pt;
|
||||
|
||||
/* Jacobian EC Point. This coordinate system uses X = x/z^2, Y = y/z^3,
|
||||
* which enables calculations with fewer inversions than affine
|
||||
* coordinates. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
} ecfp_jac_pt;
|
||||
|
||||
/* Chudnovsky Jacobian EC Point. This coordinate system is the same as
|
||||
* Jacobian, except it keeps z^2, z^3 for faster additions. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
double z2[ECFP_MAXDOUBLES];
|
||||
double z3[ECFP_MAXDOUBLES];
|
||||
} ecfp_chud_pt;
|
||||
|
||||
/* Modified Jacobian EC Point. This coordinate system is the same as
|
||||
* Jacobian, except it keeps a*z^4 for faster doublings. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
double az4[ECFP_MAXDOUBLES];
|
||||
} ecfp_jm_pt;
|
||||
|
||||
struct EC_group_fp_str;
|
||||
|
||||
typedef struct EC_group_fp_str EC_group_fp;
|
||||
struct EC_group_fp_str {
|
||||
int fpPrecision; /* Set to number of bits in mantissa, 53
|
||||
* or 64 */
|
||||
int numDoubles;
|
||||
int primeBitSize;
|
||||
int orderBitSize;
|
||||
int doubleBitSize;
|
||||
int numInts;
|
||||
int aIsM3; /* True if curvea == -3 (mod p), then we
|
||||
* can optimize doubling */
|
||||
double curvea[ECFP_MAXDOUBLES];
|
||||
/* Used to truncate a double to the number of bits in the curve */
|
||||
double bitSize_alpha;
|
||||
/* Pointer to either ecfp_alpha_53 or ecfp_alpha_64 */
|
||||
const double *alpha;
|
||||
|
||||
void (*ecfp_singleReduce) (double *r, const EC_group_fp * group);
|
||||
void (*ecfp_reduce) (double *r, double *x, const EC_group_fp * group);
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of
|
||||
* the doubles is reduced to the regular precision ECFP_DSIZE. This
|
||||
* might result in some float digits being negative. */
|
||||
void (*ecfp_tidy) (double *t, const double *alpha,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using coordinate system Jacobian + Affine
|
||||
* -> Jacobian. Input and output should be multi-precision floating
|
||||
* point integers. */
|
||||
void (*pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point doubling in Jacobian coordinates. Input and output
|
||||
* should be multi-precision floating point integers. */
|
||||
void (*pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using Jacobian coordinate system. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void (*pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point doubling in Modified Jacobian coordinates. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void (*pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point doubling using coordinates Affine -> Chudnovsky
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void (*pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using coordinates: Modified Jacobian +
|
||||
* Chudnovsky Jacobian -> Modified Jacobian. Input and output should
|
||||
* be multi-precision floating point integers. */
|
||||
void (*pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
|
||||
ecfp_jm_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point addition using Chudnovsky Jacobian coordinates.
|
||||
* Input and output should be multi-precision floating point integers.
|
||||
*/
|
||||
void (*pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
|
||||
ecfp_chud_pt * r, const EC_group_fp * group);
|
||||
/* Expects out to be an array of size 16 of Chudnovsky Jacobian
|
||||
* points. Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for
|
||||
* -15P, -13P, -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P,
|
||||
* 13P, 15P */
|
||||
void (*precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group);
|
||||
/* Expects out to be an array of size 16 of Jacobian points. Fills in
|
||||
* Chudnovsky Jacobian form (x, y, z), for O, P, 2P, ... 15P */
|
||||
void (*precompute_jac) (ecfp_jac_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group);
|
||||
|
||||
};
|
||||
|
||||
/* Computes r = x*y.
|
||||
* r must be different (point to different memory) than x and y.
|
||||
* Does not tidy or reduce. */
|
||||
void ecfp_multiply(double *r, const double *x, const double *y);
|
||||
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of the
|
||||
* doubles is reduced to the regular precision group->doubleBitSize. This
|
||||
* might result in some float digits being negative. */
|
||||
void ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group);
|
||||
|
||||
/* Performs tidying on only the upper float digits of a multi-precision
|
||||
* floating point integer, i.e. the digits beyond the regular length which
|
||||
* are removed in the reduction step. */
|
||||
void ecfp_tidyUpper(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Performs tidying on a short multi-precision floating point integer (the
|
||||
* lower group->numDoubles floats). */
|
||||
void ecfp_tidyShort(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Performs a more mathematically precise "tidying" so that each term is
|
||||
* positive. This is slower than the regular tidying, and is used for
|
||||
* conversion from floating point to integer. */
|
||||
void ecfp_positiveTidy(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Uses 4-bit window
|
||||
* method. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. The
|
||||
* parameters a, b and p are the elliptic curve coefficients and the prime
|
||||
* that determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates (Jacobian
|
||||
* coordinates for doubles and affine coordinates for additions; based on
|
||||
* recommendation from Brown et al.). Uses window NAF method (algorithm
|
||||
* 11) for scalar-point multiplication from Brown, Hankerson, Lopez,
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup);
|
||||
|
||||
/* Uses mixed Jacobian-affine coordinates to perform a point
|
||||
* multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
|
||||
* coordinates (Jacobian coordinates for doubles and affine coordinates
|
||||
* for additions; based on recommendation from Brown et al.). Not very
|
||||
* time efficient but quite space efficient, no precomputation needed.
|
||||
* group contains the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Performs calculations in floating point number format, since
|
||||
* this is faster than the integer operations on the ULTRASPARC III.
|
||||
* Uses left-to-right binary method (double & add) (algorithm 9) for
|
||||
* scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *ecgroup);
|
||||
|
||||
/* Cleans up extra memory allocated in ECGroup for this implementation. */
|
||||
void ec_GFp_extra_free_fp(ECGroup *group);
|
||||
|
||||
/* Converts from a floating point representation into an mp_int. Expects
|
||||
* that d is already reduced. */
|
||||
void
|
||||
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup);
|
||||
|
||||
/* Converts from an mpint into a floating point representation. */
|
||||
void
|
||||
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup);
|
||||
|
||||
/* Tests what precision floating point arithmetic is set to. This should
|
||||
* be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
|
||||
* (extended precision on x86) and sets it into the EC_group_fp. Returns
|
||||
* either 53 or 64 accordingly. */
|
||||
int ec_set_fp_precision(EC_group_fp * group);
|
||||
|
||||
#endif
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 160
|
||||
#define ECFP_NUMDOUBLES 7
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p, but truncates the number
|
||||
* of bits. */
|
||||
void
|
||||
ecfp160_singleReduce(double *d, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 160);
|
||||
ECFP_ASSERT(ECFP_NUMDOUBLES == 7);
|
||||
|
||||
q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_160;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
d[ECFP_NUMDOUBLES - 1] -= q;
|
||||
d[0] += q * ecfp_twom160;
|
||||
d[1] += q * ecfp_twom129;
|
||||
ecfp_positiveTidy(d, group);
|
||||
|
||||
/* Assertions for the highest order term */
|
||||
ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] / ecfp_exp[ECFP_NUMDOUBLES - 1] ==
|
||||
(unsigned long long) (d[ECFP_NUMDOUBLES - 1] /
|
||||
ecfp_exp[ECFP_NUMDOUBLES - 1]));
|
||||
ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] >= 0);
|
||||
}
|
||||
|
||||
/* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should not already be reduced, i.e. should have
|
||||
* 2*ECFP_NUMDOUBLES significant terms. x and r can be the same, but then
|
||||
* the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp160_reduce(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
|
||||
double x7, x8, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 160);
|
||||
ECFP_ASSERT(ECFP_NUMDOUBLES == 7);
|
||||
|
||||
/* Tidy just the upper bits, the lower bits can wait. */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
/* Assume that this is already tidied so that we have enough extra
|
||||
* bits */
|
||||
x7 = x[7] + x[13] * ecfp_twom129; /* adds bits 15-39 */
|
||||
|
||||
/* Tidy x7, or we won't have enough bits later to add it in */
|
||||
q = x7 + group->alpha[8];
|
||||
q -= group->alpha[8];
|
||||
x7 -= q; /* holds bits 0-24 */
|
||||
x8 = x[8] + q; /* holds bits 0-25 */
|
||||
|
||||
r[6] = x[6] + x[13] * ecfp_twom160 + x[12] * ecfp_twom129; /* adds
|
||||
* bits
|
||||
* 8-39 */
|
||||
r[5] = x[5] + x[12] * ecfp_twom160 + x[11] * ecfp_twom129;
|
||||
r[4] = x[4] + x[11] * ecfp_twom160 + x[10] * ecfp_twom129;
|
||||
r[3] = x[3] + x[10] * ecfp_twom160 + x[9] * ecfp_twom129;
|
||||
r[2] = x[2] + x[9] * ecfp_twom160 + x8 * ecfp_twom129; /* adds bits
|
||||
* 8-40 */
|
||||
r[1] = x[1] + x8 * ecfp_twom160 + x7 * ecfp_twom129; /* adds bits
|
||||
* 8-39 */
|
||||
r[0] = x[0] + x7 * ecfp_twom160;
|
||||
|
||||
/* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions
|
||||
* is accurate plus or minus one. (Rather than tidy all to make it
|
||||
* totally accurate, which is more costly.) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive result */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_160;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] += q * ecfp_twom160;
|
||||
r[1] += q * ecfp_twom129;
|
||||
|
||||
/* Tidy the result */
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_secp160r1_fp(ECGroup *group)
|
||||
{
|
||||
|
||||
EC_group_fp *fpg = NULL;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 161;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp160_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp160_reduce;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp160_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp160_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp160_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp160_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp160_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp160_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp160_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp160_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp160_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO160 * fpg->alpha[0];
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 192
|
||||
#define ECFP_NUMDOUBLES 8
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p. */
|
||||
void
|
||||
ecfp192_singleReduce(double *d, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 192);
|
||||
ECFP_ASSERT(group->numDoubles == 8);
|
||||
|
||||
q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_192;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
d[ECFP_NUMDOUBLES - 1] -= q;
|
||||
d[0] += q * ecfp_twom192;
|
||||
d[2] += q * ecfp_twom128;
|
||||
ecfp_positiveTidy(d, group);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should be be an array of at least 16, and r at least 8 x and
|
||||
* r can be the same, but then the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp_reduce_192(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
double x8, x9, x10, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 192);
|
||||
ECFP_ASSERT(group->numDoubles == 8);
|
||||
|
||||
/* Tidy just the upper portion, the lower part can wait */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
x8 = x[8] + x[14] * ecfp_twom128; /* adds bits 16-40 */
|
||||
x9 = x[9] + x[15] * ecfp_twom128; /* adds bits 16-40 */
|
||||
|
||||
/* Tidy up, or we won't have enough bits later to add it in */
|
||||
|
||||
q = x8 + group->alpha[9];
|
||||
q -= group->alpha[9];
|
||||
x8 -= q;
|
||||
x9 += q;
|
||||
|
||||
q = x9 + group->alpha[10];
|
||||
q -= group->alpha[10];
|
||||
x9 -= q;
|
||||
x10 = x[10] + q;
|
||||
|
||||
r[7] = x[7] + x[15] * ecfp_twom192 + x[13] * ecfp_twom128; /* adds
|
||||
* bits
|
||||
* 0-40 */
|
||||
r[6] = x[6] + x[14] * ecfp_twom192 + x[12] * ecfp_twom128;
|
||||
r[5] = x[5] + x[13] * ecfp_twom192 + x[11] * ecfp_twom128;
|
||||
r[4] = x[4] + x[12] * ecfp_twom192 + x10 * ecfp_twom128;
|
||||
r[3] = x[3] + x[11] * ecfp_twom192 + x9 * ecfp_twom128; /* adds bits
|
||||
* 0-40 */
|
||||
r[2] = x[2] + x10 * ecfp_twom192 + x8 * ecfp_twom128;
|
||||
r[1] = x[1] + x9 * ecfp_twom192; /* adds bits 16-40 */
|
||||
r[0] = x[0] + x8 * ecfp_twom192;
|
||||
|
||||
/*
|
||||
* Tidy up just r[group->numDoubles-2] so that the number of
|
||||
* reductions is accurate plus or minus one. (Rather than tidy all to
|
||||
* make it totally accurate) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[group->numDoubles-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive res */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_192;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] += q * ecfp_twom192;
|
||||
r[2] += q * ecfp_twom128;
|
||||
|
||||
/* Tidy the result */
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_nistp192_fp(ECGroup *group)
|
||||
{
|
||||
EC_group_fp *fpg;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 192;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp192_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp_reduce_192;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp192_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp192_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp192_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp192_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp192_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp192_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp192_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp192_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp192_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO192 * fpg->alpha[0];
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 224
|
||||
#define ECFP_NUMDOUBLES 10
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p. */
|
||||
void
|
||||
ecfp224_singleReduce(double *r, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 224);
|
||||
ECFP_ASSERT(group->numDoubles == 10);
|
||||
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] -= q * ecfp_twom224;
|
||||
r[4] += q * ecfp_twom128;
|
||||
|
||||
ecfp_positiveTidy(r, group);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should be be an array of at least 20, and r at least 10 x
|
||||
* and r can be the same, but then the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp224_reduce(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
|
||||
double x10, x11, x12, x13, x14, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 224);
|
||||
ECFP_ASSERT(group->numDoubles == 10);
|
||||
|
||||
/* Tidy just the upper bits of x. Don't need to tidy the lower ones
|
||||
* yet. */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
x10 = x[10] + x[16] * ecfp_twom128;
|
||||
x11 = x[11] + x[17] * ecfp_twom128;
|
||||
x12 = x[12] + x[18] * ecfp_twom128;
|
||||
x13 = x[13] + x[19] * ecfp_twom128;
|
||||
|
||||
/* Tidy up, or we won't have enough bits later to add it in */
|
||||
q = x10 + group->alpha[11];
|
||||
q -= group->alpha[11];
|
||||
x10 -= q;
|
||||
x11 = x11 + q;
|
||||
|
||||
q = x11 + group->alpha[12];
|
||||
q -= group->alpha[12];
|
||||
x11 -= q;
|
||||
x12 = x12 + q;
|
||||
|
||||
q = x12 + group->alpha[13];
|
||||
q -= group->alpha[13];
|
||||
x12 -= q;
|
||||
x13 = x13 + q;
|
||||
|
||||
q = x13 + group->alpha[14];
|
||||
q -= group->alpha[14];
|
||||
x13 -= q;
|
||||
x14 = x[14] + q;
|
||||
|
||||
r[9] = x[9] + x[15] * ecfp_twom128 - x[19] * ecfp_twom224;
|
||||
r[8] = x[8] + x14 * ecfp_twom128 - x[18] * ecfp_twom224;
|
||||
r[7] = x[7] + x13 * ecfp_twom128 - x[17] * ecfp_twom224;
|
||||
r[6] = x[6] + x12 * ecfp_twom128 - x[16] * ecfp_twom224;
|
||||
r[5] = x[5] + x11 * ecfp_twom128 - x[15] * ecfp_twom224;
|
||||
r[4] = x[4] + x10 * ecfp_twom128 - x14 * ecfp_twom224;
|
||||
r[3] = x[3] - x13 * ecfp_twom224;
|
||||
r[2] = x[2] - x12 * ecfp_twom224;
|
||||
r[1] = x[1] - x11 * ecfp_twom224;
|
||||
r[0] = x[0] - x10 * ecfp_twom224;
|
||||
|
||||
/*
|
||||
* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions
|
||||
* is accurate plus or minus one. (Rather than tidy all to make it
|
||||
* totally accurate) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive res */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] -= q * ecfp_twom224;
|
||||
r[4] += q * ecfp_twom128;
|
||||
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_nistp224_fp(ECGroup *group)
|
||||
{
|
||||
|
||||
EC_group_fp *fpg;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 224;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp224_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp224_reduce;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp224_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp224_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp224_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp224_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp224_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp224_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp224_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp224_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp224_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO224 * fpg->alpha[0];
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,855 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* This source file is meant to be included by other source files
|
||||
* (ecp_fp###.c, where ### is one of 160, 192, 224) and should not
|
||||
* constitute an independent compilation unit. It requires the following
|
||||
* preprocessor definitions be made: ECFP_BSIZE - the number of bits in
|
||||
* the field's prime
|
||||
* ECFP_NUMDOUBLES - the number of doubles to store one
|
||||
* multi-precision integer in floating point
|
||||
|
||||
/* Adds a prefix to a given token to give a unique token name. Prefixes
|
||||
* with "ecfp" + ECFP_BSIZE + "_". e.g. if ECFP_BSIZE = 160, then
|
||||
* PREFIX(hello) = ecfp160_hello This optimization allows static function
|
||||
* linking and compiler loop unrolling without code duplication. */
|
||||
#ifndef PREFIX
|
||||
#define PREFIX(b) PREFIX1(ECFP_BSIZE, b)
|
||||
#define PREFIX1(bsize, b) PREFIX2(bsize, b)
|
||||
#define PREFIX2(bsize, b) ecfp ## bsize ## _ ## b
|
||||
#endif
|
||||
|
||||
/* Returns true iff every double in d is 0. (If d == 0 and it is tidied,
|
||||
* this will be true.) */
|
||||
mp_err PREFIX(isZero) (const double *d) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
if (d[i] != 0)
|
||||
return MP_NO;
|
||||
}
|
||||
return MP_YES;
|
||||
}
|
||||
|
||||
/* Sets the multi-precision floating point number at t = 0 */
|
||||
void PREFIX(zero) (double *t) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
t[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets the multi-precision floating point number at t = 1 */
|
||||
void PREFIX(one) (double *t) {
|
||||
int i;
|
||||
|
||||
t[0] = 1;
|
||||
for (i = 1; i < ECFP_NUMDOUBLES; i++) {
|
||||
t[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z) is at infinity. Uses Jacobian coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_jac) (const ecfp_jac_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_jac) (ecfp_jac_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y) is at infinity. Uses Affine coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_aff) (const ecfp_aff_pt * p) {
|
||||
if (PREFIX(isZero) (p->x) == MP_YES && PREFIX(isZero) (p->y) == MP_YES)
|
||||
return MP_YES;
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
/* Sets the affine point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_aff) (ecfp_aff_pt * p) {
|
||||
PREFIX(zero) (p->x);
|
||||
PREFIX(zero) (p->y);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z, a*z^4) is at infinity. Uses Modified
|
||||
* Jacobian coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_jm) (const ecfp_jm_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Modified Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_jm) (ecfp_jm_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z, z^2, z^3) is at infinity. Uses Chudnovsky
|
||||
* Jacobian coordinates */
|
||||
mp_err PREFIX(pt_is_inf_chud) (const ecfp_chud_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Chudnovsky Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_chud) (ecfp_chud_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Copies a multi-precision floating point number, Setting dest = src */
|
||||
void PREFIX(copy) (double *dest, const double *src) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets dest = -src */
|
||||
void PREFIX(negLong) (double *dest, const double *src) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
dest[i] = -src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets r = -p p = (x, y, z, z2, z3) r = (x, -y, z, z2, z3) Uses
|
||||
* Chudnovsky Jacobian coordinates. */
|
||||
/* TODO reverse order */
|
||||
void PREFIX(pt_neg_chud) (const ecfp_chud_pt * p, ecfp_chud_pt * r) {
|
||||
int i;
|
||||
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->z2, p->z2);
|
||||
PREFIX(copy) (r->z3, p->z3);
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
r->y[i] = -p->y[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise adds first ECFP_NUMDOUBLES
|
||||
* doubles of x and y and stores the result in r. */
|
||||
void PREFIX(addShort) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ + *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise adds first
|
||||
* 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(addLong) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ + *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise subtracts first
|
||||
* ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(subtractShort) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ - *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise subtracts first
|
||||
* 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(subtractLong) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ - *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x*y. Both x and y should be tidied and reduced,
|
||||
* r must be different (point to different memory) than x and y.
|
||||
* Does not tidy or reduce. */
|
||||
void PREFIX(multiply)(double *r, const double *x, const double *y) {
|
||||
int i, j;
|
||||
|
||||
for(j=0;j<ECFP_NUMDOUBLES-1;j++) {
|
||||
r[j] = x[0] * y[j];
|
||||
r[j+(ECFP_NUMDOUBLES-1)] = x[ECFP_NUMDOUBLES-1] * y[j];
|
||||
}
|
||||
r[ECFP_NUMDOUBLES-1] = x[0] * y[ECFP_NUMDOUBLES-1];
|
||||
r[ECFP_NUMDOUBLES-1] += x[ECFP_NUMDOUBLES-1] * y[0];
|
||||
r[2*ECFP_NUMDOUBLES-2] = x[ECFP_NUMDOUBLES-1] * y[ECFP_NUMDOUBLES-1];
|
||||
r[2*ECFP_NUMDOUBLES-1] = 0;
|
||||
|
||||
for(i=1;i<ECFP_NUMDOUBLES-1;i++) {
|
||||
for(j=0;j<ECFP_NUMDOUBLES;j++) {
|
||||
r[i+j] += (x[i] * y[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the square of x and stores the result in r. x should be
|
||||
* tidied & reduced, r will be neither tidied nor reduced.
|
||||
* r should point to different memory than x */
|
||||
void PREFIX(square) (double *r, const double *x) {
|
||||
PREFIX(multiply) (r, x, x);
|
||||
}
|
||||
|
||||
/* Perform a point doubling in Jacobian coordinates. Input and output
|
||||
* should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
|
||||
const EC_group_fp * group) {
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (PREFIX(pt_is_inf_jac) (dp) == MP_YES) {
|
||||
/* Set r = pt at infinity */
|
||||
PREFIX(set_pt_inf_jac) (dr);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Perform typical point doubling operations */
|
||||
|
||||
/* TODO? is it worthwhile to do optimizations for when pz = 1? */
|
||||
|
||||
if (group->aIsM3) {
|
||||
/* When a = -3, M = 3(px - pz^2)(px + pz^2) */
|
||||
PREFIX(square) (t1, dp->z);
|
||||
group->ecfp_reduce(t1, t1, group); /* 2^23 since the negative
|
||||
* rounding buys another bit */
|
||||
PREFIX(addShort) (t0, dp->x, t1); /* 2*2^23 */
|
||||
PREFIX(subtractShort) (t1, dp->x, t1); /* 2 * 2^23 */
|
||||
PREFIX(multiply) (M, t0, t1); /* 40 * 2^46 */
|
||||
PREFIX(addLong) (t0, M, M); /* 80 * 2^46 */
|
||||
PREFIX(addLong) (M, t0, M); /* 120 * 2^46 < 2^53 */
|
||||
group->ecfp_reduce(M, M, group);
|
||||
} else {
|
||||
/* Generic case */
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
PREFIX(square) (t0, dp->x);
|
||||
PREFIX(addLong) (M, t0, t0);
|
||||
PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */
|
||||
PREFIX(square) (M, dp->z);
|
||||
group->ecfp_reduce(M, M, group);
|
||||
PREFIX(square) (t1, M);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (M, t1, group->curvea); /* M = a(pz^4) */
|
||||
PREFIX(addLong) (M, M, t0);
|
||||
group->ecfp_reduce(M, M, group);
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
PREFIX(multiply) (t1, dp->y, dp->z);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(dr->z, t1, group);
|
||||
|
||||
/* t0 = 2y^2 */
|
||||
PREFIX(square) (t0, dp->y);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(addShort) (t0, t0, t0);
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
PREFIX(multiply) (S, dp->x, t0);
|
||||
PREFIX(addLong) (S, S, S);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
PREFIX(square) (t1, M);
|
||||
PREFIX(subtractShort) (t1, t1, S);
|
||||
PREFIX(subtractShort) (t1, t1, S);
|
||||
group->ecfp_reduce(dr->x, t1, group);
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
PREFIX(square) (t1, t0); /* t1 = 4y^4 */
|
||||
PREFIX(subtractShort) (S, S, dr->x);
|
||||
PREFIX(multiply) (t0, M, S);
|
||||
PREFIX(subtractLong) (t0, t0, t1);
|
||||
PREFIX(subtractLong) (t0, t0, t1);
|
||||
group->ecfp_reduce(dr->y, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using coordinate system Jacobian + Affine ->
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void PREFIX(pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group) {
|
||||
/* Temporary storage */
|
||||
double A[2 * ECFP_NUMDOUBLES], B[2 * ECFP_NUMDOUBLES],
|
||||
C[2 * ECFP_NUMDOUBLES], C2[2 * ECFP_NUMDOUBLES],
|
||||
D[2 * ECFP_NUMDOUBLES], C3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p or q */
|
||||
if (PREFIX(pt_is_inf_aff) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
goto CLEANUP;
|
||||
} else if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
/* Since the affine point is not infinity, we can set r->z = 1 */
|
||||
PREFIX(one) (r->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Calculates c = qx * pz^2 - px d = (qy * b - py) rx = d^2 - c^3 + 2
|
||||
* (px * c^2) ry = d * (c-rx) - py*c^3 rz = c * pz */
|
||||
|
||||
/* A = pz^2, B = pz^3 */
|
||||
PREFIX(square) (A, p->z);
|
||||
group->ecfp_reduce(A, A, group);
|
||||
PREFIX(multiply) (B, A, p->z);
|
||||
group->ecfp_reduce(B, B, group);
|
||||
|
||||
/* C = qx * A - px */
|
||||
PREFIX(multiply) (C, q->x, A);
|
||||
PREFIX(subtractShort) (C, C, p->x);
|
||||
group->ecfp_reduce(C, C, group);
|
||||
|
||||
/* D = qy * B - py */
|
||||
PREFIX(multiply) (D, q->y, B);
|
||||
PREFIX(subtractShort) (D, D, p->y);
|
||||
group->ecfp_reduce(D, D, group);
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
PREFIX(square) (C2, C);
|
||||
group->ecfp_reduce(C2, C2, group);
|
||||
PREFIX(multiply) (C3, C2, C);
|
||||
group->ecfp_reduce(C3, C3, group);
|
||||
|
||||
/* rz = A = pz * C */
|
||||
PREFIX(multiply) (A, p->z, C);
|
||||
group->ecfp_reduce(r->z, A, group);
|
||||
|
||||
/* C = px * C^2, untidied, unreduced */
|
||||
PREFIX(multiply) (C, p->x, C2);
|
||||
|
||||
/* A = D^2, untidied, unreduced */
|
||||
PREFIX(square) (A, D);
|
||||
|
||||
/* rx = B = A - C3 - C - C = D^2 - (C^3 + 2 * (px * C^2) */
|
||||
PREFIX(subtractShort) (A, A, C3);
|
||||
PREFIX(subtractLong) (A, A, C);
|
||||
PREFIX(subtractLong) (A, A, C);
|
||||
group->ecfp_reduce(r->x, A, group);
|
||||
|
||||
/* B = py * C3, untidied, unreduced */
|
||||
PREFIX(multiply) (B, p->y, C3);
|
||||
|
||||
/* C = px * C^2 - rx */
|
||||
PREFIX(subtractShort) (C, C, r->x);
|
||||
group->ecfp_reduce(C, C, group);
|
||||
|
||||
/* ry = A = D * C - py * C^3 */
|
||||
PREFIX(multiply) (A, D, C);
|
||||
PREFIX(subtractLong) (A, A, B);
|
||||
group->ecfp_reduce(r->y, A, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using Jacobian coordinate system. Input and
|
||||
* output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group) {
|
||||
|
||||
/* Temporary Storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_jac) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 , S = py * qz^3 */
|
||||
PREFIX(square) (t0, q->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (U, p->x, t0);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
PREFIX(multiply) (t1, t0, q->z);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, p->y, t1);
|
||||
group->ecfp_reduce(S, t0, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U , R = (qy * pz^3 - S) */
|
||||
PREFIX(square) (t0, p->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (H, q->x, t0);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
PREFIX(multiply) (t1, t0, p->z); /* t1 = pz^3 */
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, t1, q->y); /* t0 = qy * pz^3 */
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(R, t0, group);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t0, q->z, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, p->z);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point doubling in Modified Jacobian coordinates. Input and
|
||||
* output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
|
||||
const EC_group_fp * group) {
|
||||
|
||||
/* Temporary storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], T[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
PREFIX(set_pt_inf_jm) (r);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
PREFIX(square) (t0, p->x);
|
||||
PREFIX(addLong) (M, t0, t0);
|
||||
PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */
|
||||
PREFIX(addShort) (t0, t0, p->az4);
|
||||
group->ecfp_reduce(M, t0, group);
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
PREFIX(multiply) (t1, p->y, p->z);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* t0 = 2y^2, U = 8y^4 */
|
||||
PREFIX(square) (t0, p->y);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(addShort) (t0, t0, t0);
|
||||
PREFIX(square) (U, t0);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
PREFIX(addShort) (U, U, U);
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
PREFIX(multiply) (S, p->x, t0);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
PREFIX(addShort) (S, S, S);
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
PREFIX(square) (T, M);
|
||||
PREFIX(subtractShort) (T, T, S);
|
||||
PREFIX(subtractShort) (T, T, S);
|
||||
group->ecfp_reduce(r->x, T, group);
|
||||
|
||||
/* ry = M * (S - rx) - U */
|
||||
PREFIX(subtractShort) (S, S, r->x);
|
||||
PREFIX(multiply) (t0, M, S);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->y, t0, group);
|
||||
|
||||
/* ra*z^4 = 2*U*(apz4) */
|
||||
PREFIX(multiply) (t1, U, p->az4);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(r->az4, t1, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point doubling using coordinates Affine -> Chudnovsky
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void PREFIX(pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
|
||||
const EC_group_fp * group) {
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], twoY2[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = O */
|
||||
if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
|
||||
PREFIX(set_pt_inf_chud) (r);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3(px)^2 + a */
|
||||
PREFIX(square) (t0, p->x);
|
||||
PREFIX(addLong) (t1, t0, t0);
|
||||
PREFIX(addLong) (t1, t1, t0);
|
||||
PREFIX(addShort) (t1, t1, group->curvea);
|
||||
group->ecfp_reduce(M, t1, group);
|
||||
|
||||
/* twoY2 = 2*(py)^2, S = 4(px)(py)^2 */
|
||||
PREFIX(square) (twoY2, p->y);
|
||||
PREFIX(addLong) (twoY2, twoY2, twoY2);
|
||||
group->ecfp_reduce(twoY2, twoY2, group);
|
||||
PREFIX(multiply) (S, p->x, twoY2);
|
||||
PREFIX(addLong) (S, S, S);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
PREFIX(square) (t0, M);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = M(S-rx) - 8y^4 */
|
||||
PREFIX(subtractShort) (t0, S, r->x);
|
||||
PREFIX(multiply) (t1, t0, M);
|
||||
PREFIX(square) (t0, twoY2);
|
||||
PREFIX(subtractLong) (t1, t1, t0);
|
||||
PREFIX(subtractLong) (t1, t1, t0);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
/* rz = 2py */
|
||||
PREFIX(addShort) (r->z, p->y, p->y);
|
||||
|
||||
/* rz2 = rz^2 */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(r->z2, t0, group);
|
||||
|
||||
/* rz3 = rz^3 */
|
||||
PREFIX(multiply) (t0, r->z, r->z2);
|
||||
group->ecfp_reduce(r->z3, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using coordinates: Modified Jacobian +
|
||||
* Chudnovsky Jacobian -> Modified Jacobian. Input and output should be
|
||||
* multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
|
||||
ecfp_jm_pt * r, const EC_group_fp * group) {
|
||||
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES], pz2[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q need to convert
|
||||
* from Chudnovsky form to Modified Jacobian form */
|
||||
if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
PREFIX(square) (t0, q->z2);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, group->curvea);
|
||||
group->ecfp_reduce(r->az4, t1, group);
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Check for point at infinity for q, if so set r = p */
|
||||
if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->az4, p->az4);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 */
|
||||
PREFIX(multiply) (U, p->x, q->z2);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U */
|
||||
PREFIX(square) (t0, p->z);
|
||||
group->ecfp_reduce(pz2, t0, group);
|
||||
PREFIX(multiply) (H, pz2, q->x);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* S = py * qz^3 */
|
||||
PREFIX(multiply) (S, p->y, q->z3);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* R = (qy * z1^3 - s) */
|
||||
PREFIX(multiply) (t0, pz2, p->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (R, t0, q->y);
|
||||
PREFIX(subtractShort) (R, R, S);
|
||||
group->ecfp_reduce(R, R, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t1, q->z, H);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, p->z, t1);
|
||||
group->ecfp_reduce(r->z, t0, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
if (group->aIsM3) { /* a == -3 */
|
||||
/* a(rz^4) = -3 * ((rz^2)^2) */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(square) (t1, t0);
|
||||
PREFIX(addLong) (t0, t1, t1);
|
||||
PREFIX(addLong) (t0, t0, t1);
|
||||
PREFIX(negLong) (t0, t0);
|
||||
group->ecfp_reduce(r->az4, t0, group);
|
||||
} else { /* Generic case */
|
||||
/* a(rz^4) = a * ((rz^2)^2) */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(square) (t1, t0);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, group->curvea, t1);
|
||||
group->ecfp_reduce(r->az4, t0, group);
|
||||
}
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using Chudnovsky Jacobian coordinates. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
|
||||
ecfp_chud_pt * r, const EC_group_fp * group) {
|
||||
|
||||
/* Temporary Storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_chud) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
PREFIX(copy) (r->z2, q->z2);
|
||||
PREFIX(copy) (r->z3, q->z3);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->z2, p->z2);
|
||||
PREFIX(copy) (r->z3, p->z3);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 */
|
||||
PREFIX(multiply) (U, p->x, q->z2);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U */
|
||||
PREFIX(multiply) (H, q->x, p->z2);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* S = py * qz^3 */
|
||||
PREFIX(multiply) (S, p->y, q->z3);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t0, q->z, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, p->z);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* R = (qy * z1^3 - s) */
|
||||
PREFIX(multiply) (t0, q->y, p->z3);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(R, t0, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
/* rz2 = rz^2 */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(r->z2, t0, group);
|
||||
|
||||
/* rz3 = rz^3 */
|
||||
PREFIX(multiply) (t0, r->z, r->z2);
|
||||
group->ecfp_reduce(r->z3, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Expects out to be an array of size 16 of Chudnovsky Jacobian points.
|
||||
* Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for -15P, -13P,
|
||||
* -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P, 13P, 15P */
|
||||
void PREFIX(precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group) {
|
||||
|
||||
ecfp_chud_pt p2;
|
||||
|
||||
/* Set out[8] = P */
|
||||
PREFIX(copy) (out[8].x, p->x);
|
||||
PREFIX(copy) (out[8].y, p->y);
|
||||
PREFIX(one) (out[8].z);
|
||||
PREFIX(one) (out[8].z2);
|
||||
PREFIX(one) (out[8].z3);
|
||||
|
||||
/* Set p2 = 2P */
|
||||
PREFIX(pt_dbl_aff2chud) (p, &p2, group);
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
PREFIX(pt_add_chud) (&out[8], &p2, &out[9], group);
|
||||
PREFIX(pt_add_chud) (&out[9], &p2, &out[10], group);
|
||||
PREFIX(pt_add_chud) (&out[10], &p2, &out[11], group);
|
||||
PREFIX(pt_add_chud) (&out[11], &p2, &out[12], group);
|
||||
PREFIX(pt_add_chud) (&out[12], &p2, &out[13], group);
|
||||
PREFIX(pt_add_chud) (&out[13], &p2, &out[14], group);
|
||||
PREFIX(pt_add_chud) (&out[14], &p2, &out[15], group);
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
PREFIX(pt_neg_chud) (&out[8], &out[7]);
|
||||
PREFIX(pt_neg_chud) (&out[9], &out[6]);
|
||||
PREFIX(pt_neg_chud) (&out[10], &out[5]);
|
||||
PREFIX(pt_neg_chud) (&out[11], &out[4]);
|
||||
PREFIX(pt_neg_chud) (&out[12], &out[3]);
|
||||
PREFIX(pt_neg_chud) (&out[13], &out[2]);
|
||||
PREFIX(pt_neg_chud) (&out[14], &out[1]);
|
||||
PREFIX(pt_neg_chud) (&out[15], &out[0]);
|
||||
}
|
||||
|
||||
/* Expects out to be an array of size 16 of Jacobian points. Fills in
|
||||
* Jacobian form (x, y, z), for O, P, 2P, ... 15P */
|
||||
void PREFIX(precompute_jac) (ecfp_jac_pt * precomp, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group) {
|
||||
int i;
|
||||
|
||||
/* fill precomputation table */
|
||||
/* set precomp[0] */
|
||||
PREFIX(set_pt_inf_jac) (&precomp[0]);
|
||||
/* set precomp[1] */
|
||||
PREFIX(copy) (precomp[1].x, p->x);
|
||||
PREFIX(copy) (precomp[1].y, p->y);
|
||||
if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
|
||||
PREFIX(zero) (precomp[1].z);
|
||||
} else {
|
||||
PREFIX(one) (precomp[1].z);
|
||||
}
|
||||
/* set precomp[2] */
|
||||
group->pt_dbl_jac(&precomp[1], &precomp[2], group);
|
||||
|
||||
/* set rest of precomp */
|
||||
for (i = 3; i < 16; i++) {
|
||||
group->pt_add_jac_aff(&precomp[i - 1], p, &precomp[i], group);
|
||||
}
|
||||
}
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). P and R can share x and y coordinates.
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2, z3;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_DIGITS(&z3) = 0;
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
MP_CHECKOK(mp_init(&z3));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz^2, py / pz^3) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
mp_clear(&z3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Jacobian-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (2) from Brown, Hankerson, Lopez, and
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, C2, C3;
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&C2) = 0;
|
||||
MP_DIGITS(&C3) = 0;
|
||||
MP_CHECKOK(mp_init(&A));
|
||||
MP_CHECKOK(mp_init(&B));
|
||||
MP_CHECKOK(mp_init(&C));
|
||||
MP_CHECKOK(mp_init(&D));
|
||||
MP_CHECKOK(mp_init(&C2));
|
||||
MP_CHECKOK(mp_init(&C3));
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&C2);
|
||||
mp_clear(&C3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* This routine implements Point Doubling in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1, M, S;
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&M) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
MP_CHECKOK(mp_init(&t0));
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
MP_CHECKOK(mp_init(&M));
|
||||
MP_CHECKOK(mp_init(&S));
|
||||
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
/* M = 3 * px^2 + a */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&t0, &group->curvea, &M, group->meth));
|
||||
} else if (mp_cmp_int(&group->curvea, -3) == 0) {
|
||||
/* M = 3 * (px + pz^2) * (px - pz^2) */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, &M, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &M, group->meth));
|
||||
} else {
|
||||
/* M = 3 * (px^2) + a * (pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&M, &group->curvea, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &t0, &M, group->meth));
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
/* t0 = 4 * py^2 */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, &t0, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, pz, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
}
|
||||
|
||||
/* S = 4 * px * py^2 = px * (2 * py)^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &t0, &S, group->meth));
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
MP_CHECKOK(group->meth->field_add(&S, &S, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, &t1, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t1, group->meth));
|
||||
if (mp_isodd(&t1)) {
|
||||
MP_CHECKOK(mp_add(&t1, &group->meth->irr, &t1));
|
||||
}
|
||||
MP_CHECKOK(mp_div_2(&t1, &t1));
|
||||
MP_CHECKOK(group->meth->field_sub(&S, rx, &S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&M, &S, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&M, &t1, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
mp_clear(&M);
|
||||
mp_clear(&S);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
int i, ni, d;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Uses mixed Jacobian-affine coordinates. Input and output values are
|
||||
* assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous
|
||||
* multiple point multiplication) from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
mp_int rz;
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
MP_DIGITS(&rz) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][1]));
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1],
|
||||
rx, ry, &rz, group));
|
||||
}
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_SCRATCH 6
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Modified Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *t0, *t1, *M, *S;
|
||||
|
||||
t0 = &scratch[0];
|
||||
t1 = &scratch[1];
|
||||
M = &scratch[2];
|
||||
S = &scratch[3];
|
||||
|
||||
#if MAX_SCRATCH < 4
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth));
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth));
|
||||
|
||||
/* t0 = 2y^2 , t1 = 8y^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth));
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, S, group->meth));
|
||||
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - t1 */
|
||||
MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth));
|
||||
|
||||
/* ra*z^4 = 2*t1*(apz4) */
|
||||
MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth));
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *A, *B, *C, *D, *C2, *C3;
|
||||
|
||||
A = &scratch[0];
|
||||
B = &scratch[1];
|
||||
C = &scratch[2];
|
||||
D = &scratch[3];
|
||||
C2 = &scratch[4];
|
||||
C3 = &scratch[5];
|
||||
|
||||
#if MAX_SCRATCH < 6
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
MP_CHECKOK(mp_copy(paz4, raz4));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(D, A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth));
|
||||
|
||||
/* raz4 = a * rz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz, tpx, tpy;
|
||||
mp_int raz4;
|
||||
mp_int scratch[MAX_SCRATCH];
|
||||
signed char *naf = NULL;
|
||||
int i, orderBitSize;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_DIGITS(&raz4) = 0;
|
||||
MP_DIGITS(&tpx) = 0;
|
||||
MP_DIGITS(&tpy) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_DIGITS(&scratch[i]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
MP_CHECKOK(mp_init(&tpx));
|
||||
MP_CHECKOK(mp_init(&tpy));;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(mp_init(&raz4));
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_CHECKOK(mp_init(&scratch[i]));
|
||||
}
|
||||
|
||||
/* Set out[8] = P */
|
||||
MP_CHECKOK(mp_copy(px, &precomp[8][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[8][1]));
|
||||
|
||||
/* Set (tpx, tpy) = 2P */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
|
||||
group));
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
for (i = 8; i < 15; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
|
||||
&precomp[i + 1][0], &precomp[i + 1][1],
|
||||
group));
|
||||
}
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
for (i = 0; i < 8; i++) {
|
||||
MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_neg(&precomp[15 - i][1], &precomp[i][1],
|
||||
group->meth));
|
||||
}
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
orderBitSize = mpl_significant_bits(&group->order);
|
||||
|
||||
/* Allocate memory for NAF */
|
||||
naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
|
||||
if (naf == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, orderBitSize, n, 5);
|
||||
|
||||
/* wNAF method */
|
||||
for (i = orderBitSize; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
|
||||
&raz4, scratch, group);
|
||||
if (naf[i] != 0) {
|
||||
ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
|
||||
&precomp[(naf[i] + 15) / 2][0],
|
||||
&precomp[(naf[i] + 15) / 2][1], rx, ry,
|
||||
&rz, &raz4, scratch, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
mp_clear(&scratch[i]);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
mp_clear(&tpx);
|
||||
mp_clear(&tpy);
|
||||
mp_clear(&rz);
|
||||
mp_clear(&raz4);
|
||||
free(naf);
|
||||
return res;
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Uses Montgomery reduction for field arithmetic. See mpi/mpmontg.c for
|
||||
* code implementation. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ecp.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Construct a generic GFMethod for arithmetic over prime fields with
|
||||
* irreducible irr. */
|
||||
GFMethod *
|
||||
GFMethod_consGFp_mont(const mp_int *irr)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int i;
|
||||
GFMethod *meth = NULL;
|
||||
mp_mont_modulus *mmm;
|
||||
|
||||
meth = GFMethod_consGFp(irr);
|
||||
if (meth == NULL)
|
||||
return NULL;
|
||||
|
||||
mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus));
|
||||
if (mmm == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
meth->field_mul = &ec_GFp_mul_mont;
|
||||
meth->field_sqr = &ec_GFp_sqr_mont;
|
||||
meth->field_div = &ec_GFp_div_mont;
|
||||
meth->field_enc = &ec_GFp_enc_mont;
|
||||
meth->field_dec = &ec_GFp_dec_mont;
|
||||
meth->extra1 = mmm;
|
||||
meth->extra2 = NULL;
|
||||
meth->extra_free = &ec_GFp_extra_free_mont;
|
||||
|
||||
mmm->N = meth->irr;
|
||||
mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
GFMethod_free(meth);
|
||||
return NULL;
|
||||
}
|
||||
return meth;
|
||||
}
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
|
||||
/* Field multiplication using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
#ifdef MP_MONT_USE_MP_MUL
|
||||
/* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont
|
||||
* is not implemented and we have to use mp_mul and s_mp_redc directly
|
||||
*/
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1));
|
||||
#else
|
||||
mp_int s;
|
||||
|
||||
MP_DIGITS(&s) = 0;
|
||||
/* s_mp_mul_mont doesn't allow source and destination to be the same */
|
||||
if ((a == r) || (b == r)) {
|
||||
MP_CHECKOK(mp_init(&s));
|
||||
MP_CHECKOK(s_mp_mul_mont
|
||||
(a, b, &s, (mp_mont_modulus *) meth->extra1));
|
||||
MP_CHECKOK(mp_copy(&s, r));
|
||||
mp_clear(&s);
|
||||
} else {
|
||||
return s_mp_mul_mont(a, b, r, (mp_mont_modulus *) meth->extra1);
|
||||
}
|
||||
#endif
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Field squaring using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
return ec_GFp_mul_mont(a, a, r, meth);
|
||||
}
|
||||
|
||||
/* Field division using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* if A=aZ represents a encoded in montgomery coordinates with Z and #
|
||||
* and \ respectively represent multiplication and division in
|
||||
* montgomery coordinates, then A\B = (a/b)Z = (A/B)Z and Binv =
|
||||
* (1/b)Z = (1/B)(Z^2) where B # Binv = Z */
|
||||
MP_CHECKOK(ec_GFp_div(a, b, r, meth));
|
||||
MP_CHECKOK(ec_GFp_enc_mont(r, r, meth));
|
||||
if (a == NULL) {
|
||||
MP_CHECKOK(ec_GFp_enc_mont(r, r, meth));
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Encode a field element in Montgomery form. See s_mp_to_mont in
|
||||
* mpi/mpmontg.c */
|
||||
mp_err
|
||||
ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_mont_modulus *mmm;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
mmm = (mp_mont_modulus *) meth->extra1;
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
MP_CHECKOK(s_mp_lshd(r, MP_USED(&mmm->N)));
|
||||
MP_CHECKOK(mp_mod(r, &mmm->N, r));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Decode a field element from Montgomery form. */
|
||||
mp_err
|
||||
ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Free the memory allocated to the extra fields of Montgomery GFMethod
|
||||
* object. */
|
||||
void
|
||||
ec_GFp_extra_free_mont(GFMethod *meth)
|
||||
{
|
||||
if (meth->extra1 != NULL) {
|
||||
free(meth->extra1);
|
||||
meth->extra1 = NULL;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user