Compare commits

..

18 Commits

Author SHA1 Message Date
alecf%netscape.com
e953a4ea87 C++ side of fix for bug 100212 - move consumers of nsIFile.URL into nsIIOService. r=dougt, sr=darin
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111529 18797224-902f-48f8-a5cc-f745e15eee43
2002-01-08 01:31:25 +00:00
srilatha%netscape.com
22ea3cb16d checking in for rdayal. Files already on trunk.
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111225 18797224-902f-48f8-a5cc-f745e15eee43
2002-01-02 00:08:30 +00:00
srilatha%netscape.com
e021985dac checking in for rdayal, fix for bug # 109101, r=ssu, sr=bienvenu.
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111224 18797224-902f-48f8-a5cc-f745e15eee43
2002-01-02 00:01:48 +00:00
srilatha%netscape.com
37c7fe2cc1 checking in for rdayal. fix for bug # 116993 r=ssu, sr=sspitzer.
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111223 18797224-902f-48f8-a5cc-f745e15eee43
2002-01-02 00:01:03 +00:00
srilatha%netscape.com
92449d5f2b checking in for rdayal. Fix for bug # 116993, r=ssu, sr=sspitzer
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111222 18797224-902f-48f8-a5cc-f745e15eee43
2002-01-01 23:57:54 +00:00
srilatha%netscape.com
0f4c47bad2 checking in for rdayal. Fixes for bug #s 109101 and 115307. r=ducarroz, r=ssu, sr=bienvenu, sr=sspietzer
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111221 18797224-902f-48f8-a5cc-f745e15eee43
2002-01-01 23:50:41 +00:00
cavin%netscape.com
66a09211ae Checking in for rdayal.
Bug # 106137, changes for trunk landing.
r=dougt, sr=alecf, sr=mscott.


git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@111093 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-26 23:15:27 +00:00
(no author)
4d276aa864 This commit was manufactured by cvs2svn to create branch
'MAPI_NEW_DIR_TRUNK'.

git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110704 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 09:14:30 +00:00
alecf%netscape.com
9a9d38606a removing generated files
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110679 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:26:34 +00:00
alecf%netscape.com
7ef7f62f45 remove these files from the branch
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110676 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:16:53 +00:00
alecf%netscape.com
412bc70111 argh, I'll get this right yet.. this should be #if 1
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110674 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:09:41 +00:00
alecf%netscape.com
cf982c25ce oops put that #if back
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110672 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:08:22 +00:00
alecf%netscape.com
dfb5dde44f remove some files that are no longer on this branch
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110671 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:07:50 +00:00
alecf%netscape.com
5b5ddf1efb add new files for rajiv
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110670 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:06:04 +00:00
alecf%netscape.com
2765860524 land rajiv's latest patches for MAPI support - not reviewed yet, but on the way
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110668 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 01:03:35 +00:00
alecf%netscape.com
95560e128c remove obsolete files from branch
git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@110658 18797224-902f-48f8-a5cc-f745e15eee43
2001-12-18 00:11:06 +00:00
srilatha%netscape.com
2c4edc911e Merging 094 with the private branch. Later this will be merged on to the trunk
bug #104672.


git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@107615 18797224-902f-48f8-a5cc-f745e15eee43
2001-11-07 20:16:06 +00:00
(no author)
82d37c5f89 This commit was manufactured by cvs2svn to create branch
'MAPI_NEW_DIR_TRUNK'.

git-svn-id: svn://10.0.0.236/branches/MAPI_NEW_DIR_TRUNK@107204 18797224-902f-48f8-a5cc-f745e15eee43
2001-11-03 04:06:55 +00:00
259 changed files with 4772 additions and 119694 deletions

View File

@@ -0,0 +1,70 @@
/* ***** 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) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@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 ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* This interface provides support for registering Mozilla as the default
* Mail Client. This interface can also be used to get/set the user preference
* for the default Mail Client.
*
*/
[scriptable, uuid(c5be14ba-4e0a-4eec-a1b8-04363761d63c)]
interface nsIMapiRegistry: nsISupports {
/** This is set to TRUE if Mozilla is the default Application
*/
attribute boolean isDefaultMailClient;
/** This is set TRUE only once per session.
*/
readonly attribute boolean showDialog;
/** This will bring the dialog asking the user if he/she wants to set
* Mozilla as default Mail Client.
* Call this only if Mozilla is not the default Mail client
*/
void showMailIntegrationDialog(in nsIDOMWindow parentWindow);
};
%{C++
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
%}

View File

@@ -0,0 +1,27 @@
#!nmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Srilatha Moturi <srilatha@netscape.com>
# Krishna Mohan Khandrika <kkhandrika@netscape.com>
DEPTH=..\..
DIRS=mapihook resources mapiDll
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,54 @@
; ***** 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.
;
; The Initial Developer of the Original Code is
; Netscape Communications Corp.
; Portions created by the Initial Developer are Copyright (C) 2001
; the Initial Developer. All Rights Reserved.
;
; Contributor(s): Krishna Mohan Khandrika (kkhandrika@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 *****
LIBRARY mozMapi32.dll
DESCRIPTION 'Mozilla Simple MAPI Support'
EXPORTS
MAPILogon
MAPILogoff
MAPISendMail
MAPISendDocuments
MAPIFindNext
MAPIReadMail
MAPISaveMail
MAPIDeleteMail
MAPIAddress
MAPIDetails
MAPIResolveName
MAPIFreeBuffer
GetMapiDllVersion

View File

@@ -0,0 +1,346 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@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 ***** */
#include <windows.h>
#include <tchar.h>
#include <mapidefs.h>
#include <mapi.h>
#include "msgMapi.h"
#include "msgMapiMain.h"
#define MAX_RECIPS 100
#define MAX_FILES 100
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5,
{0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
const IID IID_nsIMapi = {0x6EDCD38E,0x8861,0x11d5,
{0xA3,0xDD,0x00,0xB0,0xD0,0xF3,0xBA,0xA7}};
DWORD tId = 0;
BOOL WINAPI DllMain(HINSTANCE aInstance, DWORD aReason, LPVOID aReserved)
{
switch (aReason)
{
case DLL_PROCESS_ATTACH : tId = TlsAlloc();
if (tId == 0xFFFFFFFF)
return FALSE;
break;
case DLL_PROCESS_DETACH : TlsFree(tId);
break;
}
return TRUE;
}
BOOL InitMozillaReference(nsIMapi **aRetValue)
{
// Check wehther this thread has a valid Interface
// by looking into thread-specific-data variable
*aRetValue = (nsIMapi *)TlsGetValue(tId);
// Check whether the pointer actually resolves to
// a valid method call; otherwise mozilla is not running
if ((*aRetValue) && (*aRetValue)->IsValid() == S_OK)
return TRUE;
HRESULT hRes = ::CoInitialize(nsnull) ;
hRes = ::CoCreateInstance(CLSID_CMapiImp, NULL, CLSCTX_LOCAL_SERVER,
IID_nsIMapi, (LPVOID *)aRetValue);
if (hRes == S_OK && (*aRetValue)->Initialize() == S_OK)
if (TlsSetValue(tId, (LPVOID)(*aRetValue)))
return TRUE;
// Either CoCreate or TlsSetValue failed; so return FALSE
if ((*aRetValue))
(*aRetValue)->Release();
::CoUninitialize();
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////
// The MAPILogon function begins a Simple MAPI session, loading the default message ////
// store and address book providers ////
////////////////////////////////////////////////////////////////////////////////////////
ULONG FAR PASCAL MAPILogon(ULONG aUIParam, LPTSTR aProfileName,
LPTSTR aPassword, FLAGS aFlags,
ULONG aReserved, LPLHANDLE aSession)
{
HRESULT hr = 0;
ULONG nSessionId = 0;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
return MAPI_E_FAILURE;
if (!(aFlags & MAPI_UNICODE))
{
// Need to convert the parameters to Unicode.
char *pUserName = (char *) aProfileName;
char *pPassWord = (char *) aPassword;
TCHAR ProfileName[MAX_NAME_LEN] = {0};
TCHAR PassWord[MAX_PW_LEN] = {0};
if (pUserName != NULL)
{
if (!MultiByteToWideChar(CP_ACP, 0, pUserName, -1, ProfileName,
MAX_NAME_LEN))
return MAPI_E_FAILURE;
}
if (pPassWord != NULL)
{
if (!MultiByteToWideChar(CP_ACP, 0, pPassWord, -1, PassWord,
MAX_NAME_LEN))
return MAPI_E_FAILURE;
}
hr = pNsMapi->Login(aUIParam, ProfileName, PassWord, aFlags,
&nSessionId);
}
else
hr = pNsMapi->Login(aUIParam, aProfileName, aPassword,
aFlags, &nSessionId);
if (hr == S_OK)
(*aSession) = (LHANDLE) nSessionId;
else
return nSessionId;
return SUCCESS_SUCCESS;
}
ULONG FAR PASCAL MAPILogoff (LHANDLE aSession, ULONG aUIParam,
FLAGS aFlags, ULONG aReserved)
{
nsIMapi *pNsMapi = (nsIMapi *)TlsGetValue(tId);
if (pNsMapi != NULL)
{
if (pNsMapi->Logoff((ULONG) aSession) == S_OK)
pNsMapi->Release();
pNsMapi = NULL;
}
TlsSetValue(tId, NULL);
::CoUninitialize();
return SUCCESS_SUCCESS;
}
ULONG FAR PASCAL MAPISendMail (LHANDLE lhSession, ULONG ulUIParam, lpnsMapiMessage lpMessage,
FLAGS flFlags, ULONG ulReserved )
{
HRESULT hr = 0;
BOOL bTempSession = FALSE ;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
return MAPI_E_FAILURE;
if (lpMessage->nRecipCount > MAX_RECIPS)
return MAPI_E_TOO_MANY_RECIPIENTS ;
if (lpMessage->nFileCount > MAX_FILES)
return MAPI_E_TOO_MANY_FILES ;
if ( (!(flFlags & MAPI_DIALOG)) && (lpMessage->lpRecips == NULL) )
return MAPI_E_UNKNOWN_RECIPIENT ;
if (!lhSession || pNsMapi->IsValidSession(lhSession) != S_OK)
{
FLAGS LoginFlag ;
if ( (flFlags & MAPI_LOGON_UI) && (flFlags & MAPI_NEW_SESSION) )
LoginFlag = MAPI_LOGON_UI | MAPI_NEW_SESSION ;
else if (flFlags & MAPI_LOGON_UI)
LoginFlag = MAPI_LOGON_UI ;
hr = MAPILogon (ulUIParam, (LPTSTR) NULL, (LPTSTR) NULL, LoginFlag, 0, &lhSession) ;
if (hr != SUCCESS_SUCCESS)
return MAPI_E_LOGIN_FAILURE ;
bTempSession = TRUE ;
}
// we need to deal with null data passed in by MAPI clients, specially when MAPI_DIALOG is set.
// The MS COM type lib code generated by MIDL for the MS COM interfaces checks for these parameters
// to be non null, although null is a valid value for them here.
nsMapiRecipDesc * lpRecips ;
nsMapiFileDesc * lpFiles ;
nsMapiMessage Message ;
memset (&Message, 0, sizeof (nsMapiMessage) ) ;
nsMapiRecipDesc Recipient ;
memset (&Recipient, 0, sizeof (nsMapiRecipDesc) );
nsMapiFileDesc Files ;
memset (&Files, 0, sizeof (nsMapiFileDesc) ) ;
if(!lpMessage)
{
lpMessage = &Message ;
}
if(!lpMessage->lpRecips)
{
lpRecips = &Recipient ;
}
else
lpRecips = lpMessage->lpRecips ;
if(!lpMessage->lpFiles)
{
lpFiles = &Files ;
}
else
lpFiles = lpMessage->lpFiles ;
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
hr = pNsMapi->SendMail (lhSession, lpMessage,
(short) lpMessage->nRecipCount, lpRecips,
(short) lpMessage->nFileCount, lpFiles,
flFlags, ulReserved);
// we are seeing a problem when using Word, although we return success from the MAPI support
// MS COM interface in mozilla, we are getting this error here. This is a temporary hack !!
if (hr == 0x800703e6)
hr = SUCCESS_SUCCESS;
if (hr == SUCCESS_SUCCESS)
WaitForSingleObject (hEvent, INFINITE) ;
CloseHandle (hEvent) ;
if (bTempSession)
MAPILogoff (lhSession, ulUIParam, 0,0) ;
return hr ;
}
ULONG FAR PASCAL MAPISendDocuments(ULONG ulUIParam, LPTSTR lpszDelimChar, LPTSTR lpszFilePaths,
LPTSTR lpszFileNames, ULONG ulReserved)
{
LHANDLE lhSession ;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
return MAPI_E_FAILURE;
unsigned long result = MAPILogon (ulUIParam, (LPTSTR) NULL, (LPTSTR) NULL, MAPI_LOGON_UI, 0, &lhSession) ;
if (result != SUCCESS_SUCCESS)
return MAPI_E_LOGIN_FAILURE ;
HRESULT hr;
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
hr = pNsMapi->SendDocuments(lhSession, (LPTSTR) lpszDelimChar, (LPTSTR) lpszFilePaths,
(LPTSTR) lpszFileNames, ulReserved) ;
if (hr == SUCCESS_SUCCESS)
WaitForSingleObject (hEvent, INFINITE) ;
CloseHandle (hEvent) ;
MAPILogoff (lhSession, ulUIParam, 0,0) ;
return hr ;
}
ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageType,
LPTSTR lpszSeedMessageID, FLAGS flFlags, ULONG ulReserved,
LPTSTR lpszMessageID)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID,
FLAGS flFlags, ULONG ulReserved, lpMapiMessage FAR *lppMessage)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPISaveMail(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage,
FLAGS flFlags, ULONG ulReserved, LPTSTR lpszMessageID)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIDeleteMail(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID,
FLAGS flFlags, ULONG ulReserved)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIAddress(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszCaption,
ULONG nEditFields, LPTSTR lpszLabels, ULONG nRecips,
lpMapiRecipDesc lpRecips, FLAGS flFlags,
ULONG ulReserved, LPULONG lpnNewRecips,
lpMapiRecipDesc FAR *lppNewRecips)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIDetails(LHANDLE lhSession, ULONG ulUIParam, lpMapiRecipDesc lpRecip,
FLAGS flFlags, ULONG ulReserved)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszName,
FLAGS flFlags, ULONG ulReserved, lpMapiRecipDesc FAR *lppRecip)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIFreeBuffer(LPVOID pv)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL GetMapiDllVersion()
{
return 94;
}

View File

@@ -1,5 +1,3 @@
#!/usr/linguist/bin/perl
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@@ -13,14 +11,14 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
# Portions created by the Initial Developer are Copyright (C) 1998
# Netscape Communications Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Contributor(s): Krishna Mohan Khandrika (kkhandrika@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
@@ -34,28 +32,31 @@
# 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 *****
# ***** END LICENSE BLOCK *****
# $Id: ptab.pl,v 1.2 2005-02-02 22:28:23 gerv%gerv.net Exp $
#
DEPTH=..\..\..
while(<>) {
chomp;
push(@primes, $_);
}
MODULE = mozMapi32
EXPORT_LIBRARY = $(MODULE)
LIBRARY_NAME = $(MODULE)
DEFFILE = Mapi32.def
printf("mp_size prime_tab_size = %d;\n", ($#primes + 1));
print "mp_digit prime_tab[] = {\n";
REQUIRES = MapiProxy \
msgMapi \
xpcom \
string \
$(NULL)
print "\t";
$last = pop(@primes);
foreach $prime (sort {$a<=>$b} @primes) {
printf("0x%04X, ", $prime);
$brk = ($brk + 1) % 8;
print "\n\t" if(!$brk);
}
printf("0x%04X", $last);
print "\n" if($brk);
print "};\n\n";
include <$(DEPTH)\config\config.mak>
###############################################################
LCFLAGS=-DUNICODE -D_UNICODE
OBJS= .\$(OBJDIR)\MapiDll.obj \
$(NULL)
WIN_LIBS= ole32.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
exit 0;

View File

@@ -1,26 +1,25 @@
; ***** 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 Solaris software cryptographic token.
;
; The Initial Developer of the Original Code is
; Makoto Kato <m_kato@ga2.so-net.ne.jp>
;
; Portions created by the Initial Developer are Copyright (C) 2005
; The Original Code is Mozilla.
;
; The Initial Developer of the Original Code is
; Netscape Communications Corp.
; Portions created by the Initial Developer are Copyright (C) 2001
; the Initial Developer. All Rights Reserved.
;
; Contributor(s):
;
;
; Contributor(s): Krishna Mohan Khandrika (kkhandrika@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"),
@@ -32,28 +31,17 @@
; 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 ***** */
;
; ***** END LICENSE BLOCK *****
LIBRARY MapiProxy.dll
DESCRIPTION 'Proxy/Stub DLL'
EXPORTS
DllGetClassObject @1 PRIVATE
DllCanUnloadNow @2 PRIVATE
GetProxyDllInfo @3 PRIVATE
DllRegisterServer @4 PRIVATE
DllUnregisterServer @5 PRIVATE
.CODE
; static void cpuid(unsigned long op, unsigned long *eax,
; unsigned long *ebx, unsigned long *ecx,
; unsigned long *edx)
_cpuid PROC
mov r11, rdx
mov rax, rcx
cpuid
mov [r11], eax
mov [r8], ebx
mov [r9], ecx
mov [rsp+40], edx
ret
_cpuid ENDP
END

View File

@@ -1,4 +1,3 @@
#!/bin/sh
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@@ -12,15 +11,14 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
# Portions created by the Initial Developer are Copyright (C) 1998
# Netscape Communications Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Netscape Communications Corporation
# Contributor(s): Krishna Mohan Khandrika (kkhandrika@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
@@ -34,33 +32,37 @@
# 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 *****
# ***** END LICENSE BLOCK *****
# $Id: build,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
#
DEPTH=..\..\..\..
VERS="1.7p6"
SECT="1"
NAME="MPI Tools"
MODULE = MapiProxy
EXPORT_LIBRARY = $(MODULE)
LIBRARY_NAME = $(MODULE)
DEFFILE = MapiProxy.def
echo "Building manual pages ..."
case $# in
0)
files=`ls *.pod`
;;
*)
files=$*
;;
esac
include <$(DEPTH)\config\config.mak>
for name in $files
do
echo -n "$name ... "
# sname=`noext $name`
sname=`basename $name .pod`
pod2man --section="$SECT" --center="$NAME" --release="$VERS" $name > $sname.$SECT
echo "(done)"
done
##################################################################
LCFLAGS=-DREGISTER_PROXY_DLL -DUNICODE -D_UNICODE
OBJS= .\$(OBJDIR)\dlldata.obj \
.\$(OBJDIR)\msgMapi_p.obj \
.\$(OBJDIR)\msgMapi_i.obj \
$(NULL)
WIN_LIBS= rpcrt4.lib
EXPORTS= msgMapi.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>
msgMapi.h msgMapi_p.c msgMapi_i.c dlldata.c : msgMapi.idl
midl $(UNICODE_FLAGS) msgMapi.idl
clobber::
rm -f dlldata.c msgMapi_i.c msgMapi_p.c msgMapi.h
echo "Finished building."

View File

@@ -0,0 +1,114 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@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 ***** */
// This idl will be compiled by MIDL. MS-COM is used
// as brdige between MAPI clients and the Mozilla.
import "unknwn.idl";
typedef wchar_t LOGIN_PW_TYPE[256];
typedef struct
{
unsigned long ulReserved;
unsigned long flFlags; /* Flags */
unsigned long nPosition_NotUsed; /* character in text to be replaced by attachment */
LPTSTR lpszPathName; /* Full path name including file name */
LPTSTR lpszFileName; /* Real (original) file name */
unsigned char * lpFileType_NotUsed ;
} nsMapiFileDesc, * lpnsMapiFileDesc;
typedef struct
{
unsigned long ulReserved;
unsigned long ulRecipClass; /* MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG */
LPTSTR lpszName; /* Recipient name to display */
LPTSTR lpszAddress; /* Recipient email address */
unsigned long ulEIDSize_NotUsed;
unsigned char * lpEntryID_NotUsed ;
} nsMapiRecipDesc, * lpnsMapiRecipDesc;
typedef struct
{
unsigned long ulReserved;
LPTSTR lpszSubject; /* Message Subject */
LPTSTR lpszNoteText; /* Message Text */
LPTSTR lpszMessageType_NotUsed;
LPTSTR lpszDateReceived_notUsed; /* in YYYY/MM/DD HH:MM format */
LPTSTR lpszConversationID_NotUsed; /* conversation thread ID */
unsigned long flFlags; /* unread,return receipt */
lpnsMapiRecipDesc lpOriginator; /* Originator descriptor */
unsigned long nRecipCount; /* Number of recipients */
lpnsMapiRecipDesc lpRecips; /* Recipient descriptors */
unsigned long nFileCount; /* # of file attachments */
lpnsMapiFileDesc lpFiles; /* Attachment descriptors */
} nsMapiMessage, * lpnsMapiMessage;
[
object,
uuid(6EDCD38E-8861-11d5-A3DD-00B0D0F3BAA7),
helpstring("nsIMapi Inteface"),
pointer_default(unique)
]
interface nsIMapi : IUnknown
{
HRESULT Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
[out] unsigned long *aSessionId);
HRESULT Initialize();
HRESULT IsValid();
HRESULT IsValidSession([in] unsigned long aSession);
HRESULT SendMail([in] unsigned long aSession, [in] lpnsMapiMessage aMessage,
[in] short aRecipCount, [in, size_is(aRecipCount)] lpnsMapiRecipDesc aRecips,
[in] short aFileCount, [in, size_is(aFileCount)] lpnsMapiFileDesc aFiles,
[in] unsigned long aFlags, [in] unsigned long aReserved) ;
HRESULT SendDocuments( [in] unsigned long aSession,
[in] LPTSTR aDelimChar, [in] LPTSTR aFilePaths,
[in] LPTSTR aFileNames, [in] ULONG aFlags ) ;
HRESULT Logoff (unsigned long aSession);
HRESULT CleanUp();
};

View File

@@ -1,4 +1,3 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@@ -12,14 +11,14 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2000
# Netscape Communications Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Contributor(s): Srilatha Moturi (srilatha@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
@@ -33,11 +32,10 @@
# 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 *****
# ***** END LICENSE BLOCK *****
libfreebl_3.so {
global:
FREEBL_GetVector;
local:
*;
};
DEPTH=..\..\..
DIRS= build public src
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,5 +1,3 @@
#/bin/sh
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@@ -13,15 +11,15 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is script to change the system id in an object file from PA-RISC 2.0 to 1.1.
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Hewlett-Packard Company.
# Portions created by the Initial Developer are Copyright (C) 1999
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# wrapped by Dennis Handly on Tue Mar 23 15:23:43 1999
# Srilatha Moturi <srilatha@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
@@ -37,18 +35,15 @@
#
# ***** END LICENSE BLOCK *****
# script to change the system id in an object file from PA-RISC 2.0 to 1.1
DEPTH=..\..\..\..
adb -w $1 << EOF
?m 0 -1 0
0x0?X
0x0?W (@0x0&~0x40000)|(~@0x0&0x40000)
MODULE=msgMapi
XPIDL_MODULE=mapihook
0?"change checksum"
0x7c?X
0x7c?W (@0x7c&~0x40000)|(~@0x7c&0x40000)
$q
EOF
XPIDLSRCS = \
.\nsIMapiRegistry.idl \
.\nsIMapiSupport.idl \
$(NULL)
exit 0
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,70 @@
/* ***** 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) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@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 ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* This interface provides support for registering Mozilla as the default
* Mail Client. This interface can also be used to get/set the user preference
* for the default Mail Client.
*
*/
[scriptable, uuid(c5be14ba-4e0a-4eec-a1b8-04363761d63c)]
interface nsIMapiRegistry: nsISupports {
/** This is set to TRUE if Mozilla is the default Application
*/
attribute boolean isDefaultMailClient;
/** This is set TRUE only once per session.
*/
readonly attribute boolean showDialog;
/** This will bring the dialog asking the user if he/she wants to set
* Mozilla as default Mail Client.
* Call this only if Mozilla is not the default Mail client
*/
void showMailIntegrationDialog(in nsIDOMWindow parentWindow);
};
%{C++
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
%}

View File

@@ -11,11 +11,11 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
* 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) 2002
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
@@ -34,18 +34,31 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _SHA_256_H_
#define _SHA_256_H_
#include "nsISupports.idl"
#include "prtypes.h"
/**
* This interface provides support for registering Mozilla as a COM component
* for extending the use of Mail/News through Simple MAPI.
*
*/
struct SHA256ContextStr {
union {
PRUint32 w[64]; /* message schedule, input buffer, plus 48 words */
PRUint8 b[256];
} u;
PRUint32 h[8]; /* 8 state variables */
PRUint32 sizeHi,sizeLo; /* 64-bit count of hashed bytes. */
[noscript, uuid(8967fed2-c8bb-11d5-a3e9-00b0d0f3baa7)]
interface nsIMapiSupport : nsISupports {
/** Initiates MAPI support
*/
void initializeMAPISupport();
/** Shuts down the MAPI support
*/
void shutdownMAPISupport();
};
#endif /* _SHA_256_H_ */
%{C++
#define NS_IMAPISUPPORT_CONTRACTID "@mozilla.org/mapisupport;1"
#define NS_IMAPISUPPORT_CLASSNAME "Mozilla MAPI Support"
%}

View File

@@ -0,0 +1,323 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika <kkhandrika@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 ***** */
#undef _UNICODE
#undef UNICODE
#include <objbase.h>
#include "nsString.h"
#include "Registry.h"
#define MAPI_PROXY_DLL_NAME "MapiProxy.dll"
#define MAPI_STARTUP_ARG " /MAPIStartUp"
#define MAX_SIZE 2048
// Size of a CLSID as a string
const int CLSID_STRING_SIZE = 39;
// Proxy/Stub Dll Routines
typedef HRESULT (__stdcall ProxyServer)();
// Convert a CLSID to a char string.
BOOL CLSIDtochar(const CLSID& clsid, char* szCLSID,
int length)
{
LPOLESTR wszCLSID = NULL;
// Get CLSID
HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
if (FAILED(hr))
return FALSE;
// Covert from wide characters to non-wide.
wcstombs(szCLSID, wszCLSID, length);
// Free memory.
CoTaskMemFree(wszCLSID);
return TRUE;
}
// Create a key and set its value.
BOOL setKeyAndValue(nsCAutoString keyName, const char* subKey,
const char* theValue)
{
HKEY hKey;
BOOL retValue = TRUE;
nsCAutoString theKey(keyName);
if (subKey != NULL)
{
theKey += "\\";
theKey += subKey;
}
// Create and open key and subkey.
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, theKey.get(),
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hKey, NULL);
if (lResult != ERROR_SUCCESS)
return FALSE ;
// Set the Value.
if (theValue != NULL)
{
lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)theValue,
strlen(theValue)+1);
if (lResult != ERROR_SUCCESS)
retValue = FALSE;
}
RegCloseKey(hKey);
return TRUE;
}
// Delete a key and all of its descendents.
LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
const char* lpszKeyChild) // Key to delete
{
// Open the child.
HKEY hKeyChild ;
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
KEY_ALL_ACCESS, &hKeyChild) ;
if (lRes != ERROR_SUCCESS)
{
return lRes ;
}
// Enumerate all of the decendents of this child.
FILETIME time ;
char szBuffer[MAX_SIZE] ;
DWORD dwSize = MAX_SIZE ;
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
NULL, NULL, &time) == S_OK)
{
// Delete the decendents of this child.
lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
if (lRes != ERROR_SUCCESS)
{
// Cleanup before exiting.
RegCloseKey(hKeyChild) ;
return lRes;
}
dwSize = MAX_SIZE;
}
// Close the child.
RegCloseKey(hKeyChild) ;
// Delete this child.
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
}
void RegisterProxy()
{
HINSTANCE h = NULL;
ProxyServer *RegisterFunc = NULL;
char szModule[MAX_SIZE];
char *pTemp = NULL;
HMODULE hModule = GetModuleHandle(NULL);
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
sizeof(szModule)/sizeof(char));
if (dwResult == 0)
return;
pTemp = strrchr(szModule, '\\');
if (pTemp == NULL)
return;
*pTemp = '\0';
nsCAutoString proxyPath(szModule);
proxyPath += "\\";
proxyPath += MAPI_PROXY_DLL_NAME;
h = LoadLibrary(proxyPath.get());
if (h == NULL)
return;
RegisterFunc = (ProxyServer *) GetProcAddress(h, "DllRegisterServer");
if (RegisterFunc)
RegisterFunc();
FreeLibrary(h);
}
void UnRegisterProxy()
{
HINSTANCE h = NULL;
ProxyServer *UnRegisterFunc = NULL;
char szModule[MAX_SIZE];
char *pTemp = NULL;
HMODULE hModule = GetModuleHandle(NULL);
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
sizeof(szModule)/sizeof(char));
if (dwResult == 0)
return;
pTemp = strrchr(szModule, '\\');
if (pTemp == NULL)
return;
*pTemp = '\0';
nsCAutoString proxyPath(szModule);
proxyPath += "\\";
proxyPath += MAPI_PROXY_DLL_NAME;
h = LoadLibrary(proxyPath.get());
if (h == NULL)
return;
UnRegisterFunc = (ProxyServer *) GetProcAddress(h, "DllUnregisterServer");
if (UnRegisterFunc)
UnRegisterFunc();
FreeLibrary(h);
}
// Register the component in the registry.
HRESULT RegisterServer(const CLSID& clsid, // Class ID
const char* szFriendlyName, // Friendly Name
const char* szVerIndProgID, // Programmatic
const char* szProgID) // IDs
{
HMODULE hModule = GetModuleHandle(NULL);
char szModuleName[MAX_SIZE];
char szCLSID[CLSID_STRING_SIZE];
nsCAutoString independentProgId(szVerIndProgID);
nsCAutoString progId(szProgID);
DWORD dwResult = ::GetModuleFileName(hModule, szModuleName,
sizeof(szModuleName)/sizeof(char));
if (dwResult == 0)
return S_FALSE;
nsCAutoString moduleName(szModuleName);
nsCAutoString registryKey("CLSID\\");
moduleName += MAPI_STARTUP_ARG;
// Convert the CLSID into a char.
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
return S_FALSE;
registryKey += szCLSID;
// Add the CLSID to the registry.
if (!setKeyAndValue(registryKey, NULL, szFriendlyName))
return S_FALSE;
if (!setKeyAndValue(registryKey, "LocalServer32", moduleName.get()))
return S_FALSE;
// Add the ProgID subkey under the CLSID key.
if (!setKeyAndValue(registryKey, "ProgID", szProgID))
return S_FALSE;
// Add the version-independent ProgID subkey under CLSID key.
if (!setKeyAndValue(registryKey, "VersionIndependentProgID", szVerIndProgID))
return S_FALSE;
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
if (!setKeyAndValue(independentProgId, NULL, szFriendlyName))
return S_FALSE;
if (!setKeyAndValue(independentProgId, "CLSID", szCLSID))
return S_FALSE;
if (!setKeyAndValue(independentProgId, "CurVer", szProgID))
return S_FALSE;
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
if (!setKeyAndValue(progId, NULL, szFriendlyName))
return S_FALSE;
if (!setKeyAndValue(progId, "CLSID", szCLSID))
return S_FALSE;
RegisterProxy();
return S_OK;
}
LONG UnregisterServer(const CLSID& clsid, // Class ID
const char* szVerIndProgID, // Programmatic
const char* szProgID) // IDs
{
LONG lResult = S_OK;
// Convert the CLSID into a char.
char szCLSID[CLSID_STRING_SIZE];
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
return S_FALSE;
UnRegisterProxy();
nsCAutoString registryKey("CLSID\\");
registryKey += szCLSID;
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
if (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND)
return lResult;
registryKey += "\\LocalServer32";
// Delete only the path for this server.
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
return lResult;
// Delete the version-independent ProgID Key.
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID);
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
return lResult;
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID);
return lResult;
}

View File

@@ -11,14 +11,15 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
* 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) 2003
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Krishna Mohan Khandrika <kkhandrika@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
@@ -33,15 +34,23 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: shsign.h,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
#ifndef _SHSIGN_H_
#define _SHSIGN_H_
#ifndef _REGISTRY_H_
#define _REGISTRY_H_
#define SGN_SUFFIX ".chk"
#define NSS_SIGN_CHK_MAGIC1 0xf1
#define NSS_SIGN_CHK_MAGIC2 0xc5
#define NSS_SIGN_CHK_MAJOR_VERSION 0x01
#define NSS_SIGN_CHK_MINOR_VERSION 0x02
#include <objbase.h>
#endif /* _SHSIGN_H_ */
// This function will register a component in the Registry.
HRESULT RegisterServer(const CLSID& clsid,
const char* szFriendlyName,
const char* szVerIndProgID,
const char* szProgID) ;
// This function will unregister a component.
HRESULT UnregisterServer(const CLSID& clsid,
const char* szVerIndProgID,
const char* szProgID) ;
#endif

View File

@@ -0,0 +1,107 @@
# ***** 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) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@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 *****
DEPTH=..\..\..\..
MODULE = msgMapi
MAKE_OBJ_TYPE = DLL
LIBRARY_NAME=$(MODULE)
MODULE_NAME = $(MODULE)
REQUIRES = xpcom \
string \
MapiProxy \
appshell \
windowwatcher \
dom \
profile \
msgbase \
pref \
msgbaseutil \
msgcompo \
mailnews \
necko \
intl \
editor \
msgdb \
uriloader \
appstartup \
$(NULL)
include <$(DEPTH)\config\config.mak>
############################################################################
LCFLAGS=-DUNICODE -D_UNICODE
OBJS= \
..\build\$(OBJDIR)\msgMapi_i.obj \
.\$(OBJDIR)\msgMapiFactory.obj \
.\$(OBJDIR)\msgMapiHook.obj \
.\$(OBJDIR)\msgMapiImp.obj \
.\$(OBJDIR)\msgMapiMain.obj \
.\$(OBJDIR)\msgMapiSupport.obj \
.\$(OBJDIR)\nsMapiRegistry.obj \
.\$(OBJDIR)\nsMapiRegistryUtils.obj \
.\$(OBJDIR)\Registry.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\msgbsutl.lib \
$(LIBNSPR) \
$(NULL)
WIN_LIBS= \
ole32.lib \
$(NULL)
EXPORTS= \
msgMapiFactory.h \
msgMapiHook.h \
msgMapiImp.h \
msgMapiMain.h \
msgMapiSupport.h \
nsMapiRegistry.h \
nsMapiRegistryUtils.h \
Registry.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,118 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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 ***** */
#undef UNICODE
#undef _UNICODE
#include "msgMapiFactory.h"
#include "msgMapiImp.h"
#include "msgMapi.h"
CMapiFactory ::CMapiFactory()
: m_cRef(1)
{
}
CMapiFactory::~CMapiFactory()
{
}
STDMETHODIMP CMapiFactory::QueryInterface(const IID& aIid, void** aPpv)
{
if ((aIid == IID_IUnknown) || (aIid == IID_IClassFactory))
{
*aPpv = static_cast<IClassFactory*>(this);
}
else
{
*aPpv = nsnull;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CMapiFactory::AddRef()
{
return (PR_AtomicIncrement(&m_cRef));
}
STDMETHODIMP_(ULONG) CMapiFactory::Release()
{
PRInt32 temp;
temp = PR_AtomicDecrement(&m_cRef);
if (m_cRef == 0)
{
delete this;
return 0;
}
return temp;
}
STDMETHODIMP CMapiFactory::CreateInstance(IUnknown* aUnknownOuter,
const IID& aIid,
void** aPpv)
{
// Cannot aggregate.
if (aUnknownOuter != nsnull)
{
return CLASS_E_NOAGGREGATION ;
}
// Create component.
CMapiImp* pImp = new CMapiImp();
if (pImp == nsnull)
{
return E_OUTOFMEMORY ;
}
// Get the requested interface.
HRESULT hr = pImp->QueryInterface(aIid, aPpv);
// Release the IUnknown pointer.
// (If QueryInterface failed, component will delete itself.)
pImp->Release();
return hr;
}
STDMETHODIMP CMapiFactory::LockServer(PRBool aLock)
{
return S_OK ;
}

View File

@@ -11,15 +11,14 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Solaris software cryptographic token.
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Sun Microsystems, Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sun Microsystems, Inc.
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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
@@ -35,31 +34,36 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef MPI_AMD64
#error This file only works on AMD64 platforms.
#endif
#ifndef MSG_MAPI_FACTORY_H
#define MSG_MAPI_FACTORY_H
#include <mpi-priv.h>
#include <windows.h>
#include <objbase.h>
#include "nspr.h"
/*
* MPI glue
*
*/
/* Presently, this is only used by the Montgomery arithmetic code. */
/* c += a * b */
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len,
mp_digit b, mp_digit *c)
class CMapiFactory : public IClassFactory
{
mp_digit w;
mp_digit d;
public :
d = s_mpv_mul_add_vec64(c, a, a_len, b);
c += a_len;
while (d) {
w = c[0] + d;
d = (w < c[0] || w < d);
*c++ = w;
}
}
// IUnknown
STDMETHODIMP QueryInterface (REFIID aIid, void** aPpv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IClassFactory
STDMETHODIMP CreateInstance (LPUNKNOWN aUnkOuter, REFIID aIid, void **aPpv);
STDMETHODIMP LockServer (BOOL aLock);
CMapiFactory ();
~CMapiFactory ();
private :
PRInt32 m_cRef;
};
#endif // MSG_MAPI_FACTORY_H

View File

@@ -0,0 +1,777 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Srilatha Moturi (srilatha@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@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 MAPI_STARTUP_ARG "/MAPIStartUp"
#define MAPI_STARTUP_ARG "/MAPIStartUp"
#include <mapidefs.h>
#include <mapi.h>
#include <tchar.h>
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsISupports.h"
#include "nsIPromptService.h"
#include "nsAppShellCIDs.h"
#include "nsIDOMWindowInternal.h"
#include "nsIAppShellService.h"
#include "nsINativeAppSupport.h"
#include "nsICmdLineService.h"
#include "nsIProfileInternal.h"
#include "nsIMsgAccountManager.h"
#include "nsIDOMWindowInternal.h"
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsMsgBaseCID.h"
#include "nsIStringBundle.h"
#include "nsIPref.h"
#include "nsString.h"
#include "nsIMsgAttachment.h"
#include "nsIMsgCompFields.h"
#include "nsIMsgComposeParams.h"
#include "nsIMsgCompose.h"
#include "nsMsgCompCID.h"
#include "nsIMsgSend.h"
#include "nsIProxyObjectManager.h"
#include "nsIMsgComposeService.h"
#include "nsProxiedService.h"
#include "nsSpecialSystemDirectory.h"
#include "nsMsgI18N.h"
#include "msgMapi.h"
#include "msgMapiHook.h"
#include "msgMapiSupport.h"
#include "msgMapiMain.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
class nsMAPISendListener : public nsIMsgSendListener
{
public:
virtual ~nsMAPISendListener() { }
// nsISupports interface
NS_DECL_ISUPPORTS
/* void OnStartSending (in string aMsgID, in PRUint32 aMsgSize); */
NS_IMETHOD OnStartSending(const char *aMsgID, PRUint32 aMsgSize) { return NS_OK; }
/* void OnProgress (in string aMsgID, in PRUint32 aProgress, in PRUint32 aProgressMax); */
NS_IMETHOD OnProgress(const char *aMsgID, PRUint32 aProgress, PRUint32 aProgressMax) { return NS_OK;}
/* void OnStatus (in string aMsgID, in wstring aMsg); */
NS_IMETHOD OnStatus(const char *aMsgID, const PRUnichar *aMsg) { return NS_OK;}
/* void OnStopSending (in string aMsgID, in nsresult aStatus, in wstring aMsg, in nsIFileSpec returnFileSpec); */
NS_IMETHOD OnStopSending(const char *aMsgID, nsresult aStatus, const PRUnichar *aMsg,
nsIFileSpec *returnFileSpec) {
m_done = PR_TRUE;
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
SetEvent (hEvent) ;
CloseHandle (hEvent) ;
return NS_OK ;
}
/* void OnSendNotPerformed */
NS_IMETHOD OnSendNotPerformed(const char *aMsgID, nsresult aStatus)
{
return OnStopSending(aMsgID, aStatus, nsnull, nsnull) ;
}
/* void OnGetDraftFolderURI (); */
NS_IMETHOD OnGetDraftFolderURI(const char *aFolderURI) {return NS_OK;}
static nsresult CreateMAPISendListener( nsIMsgSendListener **ppListener);
PRBool IsDone() { return m_done ; }
protected :
nsMAPISendListener() {
NS_INIT_REFCNT();
m_done = PR_FALSE;
}
PRBool m_done;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(nsMAPISendListener, nsIMsgSendListener)
nsresult nsMAPISendListener::CreateMAPISendListener( nsIMsgSendListener **ppListener)
{
NS_ENSURE_ARG_POINTER(ppListener) ;
*ppListener = new nsMAPISendListener();
if (! *ppListener)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*ppListener);
return NS_OK;
}
PRBool nsMapiHook::isMapiService = PR_FALSE;
PRBool nsMapiHook::Initialize()
{
nsresult rv;
nsCOMPtr<nsINativeAppSupport> native;
nsCOMPtr<nsICmdLineService> cmdLineArgs(do_GetService(kCmdLineServiceCID, &rv));
if (NS_FAILED(rv)) return PR_FALSE;
nsCOMPtr<nsIAppShellService> appShell (do_GetService( "@mozilla.org/appshell/appShellService;1", &rv));
if (NS_FAILED(rv)) return PR_FALSE;
rv = appShell->GetNativeAppSupport( getter_AddRefs( native ));
if (NS_FAILED(rv)) return PR_FALSE;
rv = native->EnsureProfile(cmdLineArgs);
if (NS_FAILED(rv)) return PR_FALSE;
return PR_TRUE;
}
void nsMapiHook::CleanUp()
{
// This routine will be fully implemented in future
// to cleanup mapi related stuff inside mozilla code.
}
PRBool nsMapiHook::DisplayLoginDialog(PRBool aLogin, PRUnichar **aUsername, \
PRUnichar **aPassword)
{
nsresult rv;
PRBool btnResult = PR_FALSE;
nsCOMPtr<nsIAppShellService> appShell(do_GetService( "@mozilla.org/appshell/appShellService;1", &rv));
if (NS_FAILED(rv) || !appShell) return PR_FALSE;
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_SUCCEEDED(rv) && dlgService)
{
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
if (NS_FAILED(rv) || !bundleService) return PR_FALSE;
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
if (NS_FAILED(rv) || !bundle) return PR_FALSE;
nsCOMPtr<nsIStringBundle> brandBundle;
rv = bundleService->CreateBundle(
"chrome://global/locale/brand.properties",
getter_AddRefs(brandBundle));
if (NS_FAILED(rv)) return PR_FALSE;
nsXPIDLString brandName;
rv = brandBundle->GetStringFromName(
NS_LITERAL_STRING("brandShortName").get(),
getter_Copies(brandName));
if (NS_FAILED(rv)) return PR_FALSE;
nsXPIDLString loginTitle;
const PRUnichar *brandStrings[] = { brandName.get() };
NS_NAMED_LITERAL_STRING(loginTitlePropertyTag, "loginTitle");
const PRUnichar *dTitlePropertyTag = loginTitlePropertyTag.get();
rv = bundle->FormatStringFromName(dTitlePropertyTag, brandStrings, 1,
getter_Copies(loginTitle));
if (NS_FAILED(rv)) return PR_FALSE;
if (aLogin)
{
nsXPIDLString loginText;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("loginTextwithName").get(),
getter_Copies(loginText));
if (NS_FAILED(rv) || !loginText) return PR_FALSE;
rv = dlgService->PromptUsernameAndPassword(nsnull, loginTitle,
loginText, aUsername, aPassword,
nsnull, PR_FALSE, &btnResult);
}
else
{
//nsString loginString;
nsXPIDLString loginText;
const PRUnichar *userNameStrings[] = { *aUsername };
NS_NAMED_LITERAL_STRING(loginTextPropertyTag, "loginText");
const PRUnichar *dpropertyTag = loginTextPropertyTag.get();
rv = bundle->FormatStringFromName(dpropertyTag, userNameStrings, 1,
getter_Copies(loginText));
if (NS_FAILED(rv)) return PR_FALSE;
rv = dlgService->PromptPassword(nsnull, loginTitle, loginText,
aPassword, nsnull, PR_FALSE, &btnResult);
}
}
return btnResult;
}
PRBool nsMapiHook::VerifyUserName(const PRUnichar *aUsername, char **aIdKey)
{
nsresult rv;
if (aUsername == nsnull)
return PR_FALSE;
nsCOMPtr<nsIMsgAccountManager> accountManager(do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv));
if (NS_FAILED(rv)) return PR_FALSE;
nsCOMPtr<nsISupportsArray> identities;
rv = accountManager->GetAllIdentities(getter_AddRefs(identities));
if (NS_FAILED(rv)) return PR_FALSE;
PRUint32 numIndentities;
identities->Count(&numIndentities);
for (PRUint32 i = 0; i < numIndentities; i++)
{
// convert supports->Identity
nsCOMPtr<nsISupports> thisSupports;
rv = identities->GetElementAt(i, getter_AddRefs(thisSupports));
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIMsgIdentity> thisIdentity(do_QueryInterface(thisSupports, &rv));
if (NS_SUCCEEDED(rv) && thisIdentity)
{
nsXPIDLCString email;
rv = thisIdentity->GetEmail(getter_Copies(email));
if (NS_FAILED(rv)) continue;
// get the username from the email and compare with the username
nsCAutoString aEmail(email.get());
PRInt32 index = aEmail.FindChar('@');
if (index != -1)
aEmail.Truncate(index);
if (nsDependentString(aUsername) == NS_ConvertASCIItoUCS2(aEmail)) // == overloaded
return NS_SUCCEEDED(thisIdentity->GetKey(aIdKey));
}
}
return PR_FALSE;
}
PRBool
nsMapiHook::IsBlindSendAllowed()
{
PRBool enabled = PR_FALSE;
PRBool warn = PR_TRUE;
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
if (prefs) {
prefs->GetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND,&warn);
prefs->GetBoolPref(PREF_MAPI_BLIND_SEND_ENABLED,&enabled);
}
if (!enabled)
return PR_FALSE;
if (!warn)
return PR_TRUE; // Everything is okay.
nsresult rv;
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
if (NS_FAILED(rv) || !bundleService) return PR_FALSE;
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
if (NS_FAILED(rv) || !bundle) return PR_FALSE;
nsXPIDLString warningMsg;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("mapiBlindSendWarning").get(),
getter_Copies(warningMsg));
if (NS_FAILED(rv)) return PR_FALSE;
nsXPIDLString dontShowAgainMessage;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("mapiBlindSendDontShowAgain").get(),
getter_Copies(dontShowAgainMessage));
if (NS_FAILED(rv)) return PR_FALSE;
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_FAILED(rv) || !dlgService) return PR_FALSE;
PRBool continueToWarn = PR_TRUE;
PRBool okayToContinue = PR_FALSE;
dlgService->ConfirmCheck(nsnull, nsnull, warningMsg, dontShowAgainMessage, &continueToWarn, &okayToContinue);
if (!continueToWarn && okayToContinue && prefs)
prefs->SetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND,PR_FALSE);
return okayToContinue;
}
// this is used for Send without UI
nsresult nsMapiHook::BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (!IsBlindSendAllowed())
return NS_ERROR_FAILURE;
/** create nsIMsgComposeParams obj and other fields to populate it **/
// get parent window
nsCOMPtr<nsIAppShellService> appService = do_GetService( "@mozilla.org/appshell/appShellService;1", &rv);
if (NS_FAILED(rv)|| (!appService) ) return rv ;
nsCOMPtr<nsIDOMWindowInternal> hiddenWindow;
rv = appService->GetHiddenDOMWindow(getter_AddRefs(hiddenWindow));
if ( NS_FAILED(rv) ) return rv ;
// smtp password and Logged in used IdKey from MapiConfig (session obj)
nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
if (!pMapiConfig) return NS_ERROR_FAILURE ; // get the singelton obj
PRUnichar * password = pMapiConfig->GetPassword(aSession) ;
// password
nsCAutoString smtpPassword ;
smtpPassword.AssignWithConversion (password) ;
// Id key
char * MsgIdKey = pMapiConfig->GetIdKey(aSession) ;
// get the MsgIdentity for the above key using AccountManager
nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService (NS_MSGACCOUNTMANAGER_CONTRACTID) ;
if (NS_FAILED(rv) || (!accountManager) ) return rv ;
nsCOMPtr <nsIMsgIdentity> pMsgId ;
rv = accountManager->GetIdentity (MsgIdKey, getter_AddRefs(pMsgId)) ;
if (NS_FAILED(rv) ) return rv ;
// create a send listener to get back the send status
nsCOMPtr <nsIMsgSendListener> sendListener ;
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
if (NS_FAILED(rv) || (!sendListener) ) return rv;
// create the compose params object
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
// populate the compose params
pMsgComposeParams->SetType(nsIMsgCompType::New);
pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
pMsgComposeParams->SetIdentity(pMsgId);
pMsgComposeParams->SetComposeFields(aCompFields);
pMsgComposeParams->SetSendListener(sendListener) ;
pMsgComposeParams->SetSmtpPassword(smtpPassword.get());
// create the nsIMsgCompose object to send the object
nsCOMPtr<nsIMsgCompose> pMsgCompose (do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv));
if (NS_FAILED(rv) || (!pMsgCompose) ) return rv ;
/** initialize nsIMsgCompose, Send the message, wait for send completion response **/
rv = pMsgCompose->Initialize(hiddenWindow, pMsgComposeParams) ;
if (NS_FAILED(rv)) return rv ;
pMsgCompose->SendMsg(nsIMsgSend::nsMsgDeliverNow, pMsgId, nsnull) ;
if (NS_FAILED(rv)) return rv ;
// assign to interface pointer from nsCOMPtr to facilitate typecast below
nsIMsgSendListener * pSendListener = sendListener ;
// we need to wait here to make sure that we return only after send is completed
// so we will have a event loop here which will process the events till the Send IsDone.
nsCOMPtr<nsIEventQueueService> pEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
nsCOMPtr<nsIEventQueue> eventQueue;
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,getter_AddRefs(eventQueue));
while ( !((nsMAPISendListener *) pSendListener)->IsDone() )
eventQueue->ProcessPendingEvents();
return rv ;
}
// this is used to populate comp fields with Unicode data
nsresult nsMapiHook::PopulateCompFields(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (aMessage->lpOriginator)
{
PRUnichar * From = aMessage->lpOriginator->lpszAddress ;
aCompFields->SetFrom (From) ;
}
nsAutoString To ;
nsAutoString Cc ;
nsAutoString Bcc ;
nsAutoString Comma ;
Comma.AssignWithConversion(",");
if (aMessage->lpRecips)
{
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
{
if (aMessage->lpRecips[i].lpszAddress)
{
switch (aMessage->lpRecips[i].ulRecipClass)
{
case MAPI_TO :
if (To.Length() > 0)
To += Comma ;
To += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
break ;
case MAPI_CC :
if (Cc.Length() > 0)
Cc += Comma ;
Cc += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
break ;
case MAPI_BCC :
if (Bcc.Length() > 0)
Bcc += Comma ;
Bcc += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
break ;
}
}
}
}
// set To, Cc, Bcc
aCompFields->SetTo (To.get()) ;
aCompFields->SetCc (Cc.get()) ;
aCompFields->SetBcc (Bcc.get()) ;
// set subject
if (aMessage->lpszSubject)
{
PRUnichar * Subject = aMessage->lpszSubject ;
aCompFields->SetSubject(Subject) ;
}
// handle attachments as File URL
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, PR_TRUE) ;
if (NS_FAILED(rv)) return rv ;
// set body
if (aMessage->lpszNoteText)
{
PRUnichar * Body = aMessage->lpszNoteText ;
rv = aCompFields->SetBody(Body) ;
}
#ifdef RAJIV_DEBUG
// testing what all was set in CompFields
printf ("To : %S \n", To.get()) ;
printf ("CC : %S \n", Cc.get() ) ;
printf ("BCC : %S \n", Bcc.get() ) ;
#endif
return rv ;
}
nsresult nsMapiHook::HandleAttachments (nsIMsgCompFields * aCompFields, PRInt32 aFileCount,
lpnsMapiFileDesc aFiles, BOOL aIsUnicode)
{
nsresult rv = NS_OK ;
nsCAutoString Attachments ;
nsCAutoString TempFiles ;
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pFile) ) return rv ;
for (int i=0 ; i < aFileCount ; i++)
{
if (aFiles[i].lpszPathName)
{
// check if attachment exists
if (aIsUnicode)
pFile->InitWithUnicodePath (aFiles[i].lpszPathName) ;
else
pFile->InitWithPath ((char *) aFiles[i].lpszPathName) ;
PRBool bExist ;
rv = pFile->Exists(&bExist) ;
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
// create Msg attachment object
nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
if (NS_FAILED(rv) || (!attachment) ) return rv ;
// set url
nsXPIDLCString pURL ;
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
attachment->SetUrl(pURL) ;
if (aFiles[i].lpszFileName)
{
if (! aIsUnicode)
{
nsAutoString realFileName ;
realFileName.AssignWithConversion ((char *) aFiles[i].lpszFileName) ;
attachment->SetName(realFileName.get()) ;
// attachment->SetName( (nsDependentString(aFiles[i].lpszFileName)).get() );
}
else
attachment->SetName(aFiles[i].lpszFileName) ;
}
attachment->SetTemporary(PR_FALSE) ;
rv = aCompFields->AddAttachment (attachment);
}
}
return rv ;
}
// this is used to convert non Unicode data and then populate comp fields
nsresult nsMapiHook::PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (aMessage->lpOriginator)
{
nsAutoString From ;
From.AssignWithConversion((char *) aMessage->lpOriginator->lpszAddress);
aCompFields->SetFrom (From.get()) ;
}
nsAutoString To ;
nsAutoString Cc ;
nsAutoString Bcc ;
nsAutoString Comma ;
Comma.AssignWithConversion(",");
if (aMessage->lpRecips)
{
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
{
if (aMessage->lpRecips[i].lpszAddress)
{
switch (aMessage->lpRecips[i].ulRecipClass)
{
case MAPI_TO :
if (To.Length() > 0)
To += Comma ;
To.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress);
break ;
case MAPI_CC :
if (Cc.Length() > 0)
Cc += Comma ;
Cc.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress);
break ;
case MAPI_BCC :
if (Bcc.Length() > 0)
Bcc += Comma ;
Bcc.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress) ;
break ;
}
}
}
}
// set To, Cc, Bcc
aCompFields->SetTo (To.get()) ;
aCompFields->SetCc (Cc.get()) ;
aCompFields->SetBcc (Bcc.get()) ;
nsCAutoString platformCharSet;
// set subject
if (aMessage->lpszSubject)
{
nsAutoString Subject ;
if (platformCharSet.IsEmpty())
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszSubject, Subject);
if (NS_FAILED(rv)) return rv ;
aCompFields->SetSubject(Subject.get()) ;
}
// handle attachments as File URL
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, PR_FALSE) ;
if (NS_FAILED(rv)) return rv ;
// set body
if (aMessage->lpszNoteText)
{
nsAutoString Body ;
if (platformCharSet.IsEmpty())
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszNoteText, Body);
if (NS_FAILED(rv)) return rv ;
rv = aCompFields->SetBody(Body.get()) ;
}
#ifdef RAJIV_DEBUG
// testing what all was set in CompFields
printf ("To : %S \n", To.get()) ;
printf ("CC : %S \n", Cc.get() ) ;
printf ("BCC : %S \n", Bcc.get() ) ;
#endif
return rv ;
}
// this is used to populate the docs as attachments in the Comp fields for Send Documents
nsresult nsMapiHook::PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields, ULONG aFlags,
PRUnichar * aDelimChar, PRUnichar * aFilePaths)
{
nsAutoString strDelimChars ;
nsString strFilePaths;
nsresult rv = NS_OK ;
if (aFlags & MAPI_UNICODE)
{
if (aDelimChar)
strDelimChars.Assign (aDelimChar) ;
if (aFilePaths)
strFilePaths.Assign (aFilePaths) ;
}
else
{
if (aDelimChar)
strDelimChars.AssignWithConversion ((char*) aDelimChar) ;
if (aFilePaths)
strFilePaths.AssignWithConversion ((char *) aFilePaths) ;
}
// check for comma in filename
if (strDelimChars.Find (",") == kNotFound) // if comma is not in the delimiter specified by user
{
if (strFilePaths.Find(",") != kNotFound) // if comma found in filenames return error
return NS_ERROR_FILE_INVALID_PATH ;
}
nsCString Attachments ;
// only 1 file is to be sent, no delim specified
if ((!strDelimChars.Length()) && (strFilePaths.Length()>0))
{
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pFile) ) return rv ;
pFile->InitWithUnicodePath (strFilePaths.get()) ;
PRBool bExist ;
rv = pFile->Exists(&bExist) ;
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
nsXPIDLCString pURL ;
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
if (pURL)
Attachments.Assign(pURL) ;
// set attachments for comp field and return
rv = aCompFields->SetAttachments (Attachments.get());
return rv ;
}
// multiple files to be sent, delim specified
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pFile) ) return rv ;
PRInt32 offset = 0 ;
PRInt32 FilePathsLen = strFilePaths.Length() ;
if (FilePathsLen)
{
PRUnichar * newFilePaths = (PRUnichar *) strFilePaths.get() ;
while (offset != kNotFound)
{
nsString RemainingPaths ;
RemainingPaths.Assign(newFilePaths) ;
offset = RemainingPaths.Find (strDelimChars) ;
if (offset != kNotFound)
{
RemainingPaths.SetLength (offset) ;
if ((offset + strDelimChars.Length()) < FilePathsLen)
newFilePaths += offset + strDelimChars.Length() ;
}
pFile->InitWithUnicodePath (RemainingPaths.get()) ;
#ifdef RAJIV_DEBUG
printf ("File : %S \n", RemainingPaths.get()) ;
#endif
PRBool bExist ;
rv = pFile->Exists(&bExist) ;
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
nsXPIDLCString pURL ;
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
if (pURL)
{
if (Attachments.Length() > 0)
Attachments.Append(",") ;
Attachments.Append(pURL) ;
}
}
rv = aCompFields->SetAttachments (Attachments.get());
}
return rv ;
}
// this used for Send with UI
nsresult nsMapiHook::ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
// create a send listener to get back the send status
nsCOMPtr <nsIMsgSendListener> sendListener ;
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
if (NS_FAILED(rv) || (!sendListener) ) return rv ;
// create the compose params object
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
// populate the compose params
pMsgComposeParams->SetType(nsIMsgCompType::New);
pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
pMsgComposeParams->SetComposeFields(aCompFields);
pMsgComposeParams->SetSendListener(sendListener) ;
/** get the nsIMsgComposeService object to open the compose window **/
nsCOMPtr <nsIMsgComposeService> compService = do_GetService (NS_MSGCOMPOSESERVICE_CONTRACTID) ;
if (NS_FAILED(rv)|| (!compService) ) return rv ;
rv = compService->OpenComposeWindowWithParams(nsnull, pMsgComposeParams) ;
if (NS_FAILED(rv)) return rv ;
return rv ;
}

View File

@@ -11,15 +11,14 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Camellia code.
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* NTT(Nippon Telegraph and Telephone Corporation).
*
* Portions created by the Initial Developer are Copyright (C) 2006
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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
@@ -34,46 +33,34 @@
* 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
#ifndef MSG_MAPI_HOOK_H_
#define MSG_MAPI_HOOK_H_
#define CAMELLIA_BLOCK_SIZE 16 /* bytes */
#define CAMELLIA_MIN_KEYSIZE 16 /* bytes */
#define CAMELLIA_MAX_KEYSIZE 32 /* bytes */
#include "prtypes.h"
#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
class nsMapiHook
{
PRUint32 keysize; /* bytes */
CamelliaFunc *worker;
PRUint32 expandedKey[CAMELLIA_MAX_EXPANDEDKEY];
PRUint8 iv[CAMELLIA_BLOCK_SIZE];
public :
static PRBool Initialize();
static PRBool DisplayLoginDialog(PRBool aLogin, PRUnichar **aUsername,
PRUnichar **aPassword);
static PRBool VerifyUserName(const PRUnichar *aUsername, char **aIdKey);
static PRBool IsBlindSendAllowed () ;
static nsresult BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
static nsresult ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFields(lpnsMapiMessage aMessage, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields,
ULONG aFlags, LPTSTR aDelimChar, LPTSTR aFilePaths) ;
static nsresult HandleAttachments (nsIMsgCompFields * aCompFields, PRInt32 aFileCount,
lpnsMapiFileDesc aFiles, BOOL aIsUnicode) ;
static void CleanUp();
static PRBool isMapiService;
};
#endif /* _CAMELLIA_H_ */
#endif // MSG_MAPI_HOOK_H_

View File

@@ -0,0 +1,266 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@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 ***** */
#include <mapidefs.h>
#include <mapi.h>
#include "msgMapi.h"
#include "msgMapiImp.h"
#include "msgMapiFactory.h"
#include "msgMapiMain.h"
#include "nsMsgCompFields.h"
#include "msgMapiHook.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsMsgCompCID.h"
CMapiImp::CMapiImp()
: m_cRef(1)
{
m_Lock = PR_NewLock();
}
CMapiImp::~CMapiImp()
{
if (m_Lock)
PR_DestroyLock(m_Lock);
}
STDMETHODIMP CMapiImp::QueryInterface(const IID& aIid, void** aPpv)
{
if (aIid == IID_IUnknown)
{
*aPpv = static_cast<nsIMapi*>(this);
}
else if (aIid == IID_nsIMapi)
{
*aPpv = static_cast<nsIMapi*>(this);
}
else
{
*aPpv = nsnull;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CMapiImp::AddRef()
{
return PR_AtomicIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CMapiImp::Release()
{
PRInt32 temp;
temp = PR_AtomicDecrement(&m_cRef);
if (m_cRef == 0)
{
delete this;
return 0;
}
return temp;
}
STDMETHODIMP CMapiImp::IsValid()
{
return S_OK;
}
STDMETHODIMP CMapiImp::IsValidSession(unsigned long aSession)
{
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig && pConfig->IsSessionValid(aSession))
return S_OK;
return E_FAIL;
}
STDMETHODIMP CMapiImp::Initialize()
{
HRESULT hr = E_FAIL;
if (!m_Lock)
return E_FAIL;
PR_Lock(m_Lock);
// Initialize MAPI Configuration
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig != nsnull)
if (nsMapiHook::Initialize())
hr = S_OK;
PR_Unlock(m_Lock);
return hr;
}
STDMETHODIMP CMapiImp::Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin, LOGIN_PW_TYPE aPassWord,
unsigned long aFlags, unsigned long *aSessionId)
{
HRESULT hr = E_FAIL;
PRBool bNewSession = PR_FALSE;
char *id_key = nsnull;
if (aFlags & MAPI_NEW_SESSION)
bNewSession = PR_TRUE;
// Check For Profile Name
if (aLogin != nsnull && aLogin[0] != '\0')
{
if (nsMapiHook::VerifyUserName(aLogin, &id_key) == PR_FALSE)
{
*aSessionId = MAPI_E_LOGIN_FAILURE;
return hr;
}
}
// finally register(create) the session.
PRUint32 nSession_Id;
PRInt16 nResult = 0;
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig != nsnull)
nResult = pConfig->RegisterSession(aUIArg, aLogin, aPassWord,
(aFlags & MAPI_FORCE_DOWNLOAD), bNewSession,
&nSession_Id, id_key);
switch (nResult)
{
case -1 :
{
*aSessionId = MAPI_E_TOO_MANY_SESSIONS;
return hr;
}
case 0 :
{
*aSessionId = MAPI_E_INSUFFICIENT_MEMORY;
return hr;
}
default :
{
*aSessionId = nSession_Id;
break;
}
}
return S_OK;
}
STDMETHODIMP CMapiImp::SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
short aRecipCount, lpnsMapiRecipDesc aRecips , short aFileCount, lpnsMapiFileDesc aFiles ,
unsigned long aFlags, unsigned long aReserved)
{
nsresult rv = NS_OK ;
// Assign the pointers in the aMessage struct to the array of Recips and Files
// recieved here from MS COM. These are used in BlindSendMail and ShowCompWin fns
aMessage->lpRecips = aRecips ;
aMessage->lpFiles = aFiles ;
/** create nsIMsgCompFields obj and populate it **/
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
if (aFlags & MAPI_UNICODE)
rv = nsMapiHook::PopulateCompFields(aMessage, pCompFields) ;
else
rv = nsMapiHook::PopulateCompFieldsWithConversion(aMessage, pCompFields) ;
if (NS_SUCCEEDED (rv))
{
// see flag to see if UI needs to be brought up
if (!(aFlags & MAPI_DIALOG))
{
rv = nsMapiHook::BlindSendMail(aSession, pCompFields);
}
else
{
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
}
}
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
}
STDMETHODIMP CMapiImp::SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags)
{
nsresult rv = NS_OK ;
/** create nsIMsgCompFields obj and populate it **/
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
if (aFilePaths)
{
rv = nsMapiHook::PopulateCompFieldsForSendDocs(pCompFields, aFlags, aDelimChar, aFilePaths) ;
}
if (NS_SUCCEEDED (rv))
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
}
STDMETHODIMP CMapiImp::Logoff (unsigned long aSession)
{
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig->UnRegisterSession((PRUint32)aSession))
return S_OK;
return E_FAIL;
}
STDMETHODIMP CMapiImp::CleanUp()
{
nsMapiHook::CleanUp();
return S_OK;
}

View File

@@ -0,0 +1,92 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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 ***** */
#ifndef MSG_MAPI_IMP_H
#define MSG_MAPI_IMP_H
#include <windows.h>
#include <mapi.h>
#include "msgMapi.h"
#include "nsXPIDLString.h"
#include "nspr.h"
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5, {0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
// this class implements the MS COM interface nsIMapi that provides the methods
// called by mapi32.dll to perform the mail operations as specified by MAPI.
// These class methods in turn use the Mozilla Mail XPCOM interfaces to do so.
class CMapiImp : public nsIMapi
{
public :
// IUnknown
STDMETHODIMP QueryInterface(const IID& aIid, void** aPpv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// Interface INsMapi
STDMETHODIMP Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
unsigned long *aSessionId);
STDMETHODIMP SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
short aRecipCount, lpnsMapiRecipDesc aRecips ,
short aFileCount, lpnsMapiFileDesc aFiles ,
unsigned long aFlags, unsigned long aReserved) ;
STDMETHODIMP SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags);
STDMETHODIMP Initialize();
STDMETHODIMP IsValid();
STDMETHODIMP IsValidSession(unsigned long aSession);
STDMETHODIMP Logoff (unsigned long aSession);
STDMETHODIMP CleanUp();
CMapiImp();
~CMapiImp();
private :
PRLock *m_Lock;
PRInt32 m_cRef;
};
#endif // MSG_MAPI_IMP_H

View File

@@ -0,0 +1,376 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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 ***** */
#include <mapidefs.h>
#include <mapi.h>
#include "msgCore.h"
#include "nsMsgComposeStringBundle.h"
#include "msgMapiMain.h"
#include "nsIServiceManager.h"
#include "nsCOMPtr.h"
// move to xpcom bug 81956.
class nsPRUintKey : public nsHashKey {
protected:
PRUint32 mKey;
public:
nsPRUintKey(PRUint32 key) : mKey(key) {}
PRUint32 HashCode(void) const {
return mKey;
}
PRBool Equals(const nsHashKey *aKey) const {
return mKey == ((const nsPRUintKey *) aKey)->mKey;
}
nsHashKey *Clone() const {
return new nsPRUintKey(mKey);
}
PRUint32 GetValue() { return mKey; }
};
//
nsMAPIConfiguration *nsMAPIConfiguration::m_pSelfRef = nsnull;
PRUint32 nsMAPIConfiguration::session_generator = 0;
PRUint32 nsMAPIConfiguration::sessionCount = 0;
nsMAPIConfiguration *nsMAPIConfiguration::GetMAPIConfiguration()
{
if (m_pSelfRef == nsnull)
m_pSelfRef = new nsMAPIConfiguration();
return m_pSelfRef;
}
nsMAPIConfiguration::nsMAPIConfiguration()
: m_nMaxSessions(MAX_SESSIONS)
{
m_Lock = PR_NewLock();
}
static PRBool
FreeSessionMapEntries(nsHashKey *aKey, void *aData, void* aClosure)
{
nsMAPISession *pTemp = (nsMAPISession*) aData;
if (pTemp)
{
delete pTemp;
pTemp = nsnull;
}
return PR_TRUE;
}
static PRBool
FreeProfileMapEntries(nsHashKey *aKey, void *aData, void* aClosure)
{
return PR_TRUE;
}
nsMAPIConfiguration::~nsMAPIConfiguration()
{
if (m_Lock)
PR_DestroyLock(m_Lock);
m_SessionMap.Reset(FreeSessionMapEntries);
m_ProfileMap.Reset(FreeProfileMapEntries);
}
void nsMAPIConfiguration::OpenConfiguration()
{
// No. of max. sessions is set to MAX_SESSIONS. In future
// if it is decided to have configuration (registry)
// parameter, this function can be used to set the
// max sessions;
return;
}
PRInt16 nsMAPIConfiguration::RegisterSession(PRUint32 aHwnd,
const PRUnichar *aUserName, const PRUnichar *aPassword,
PRBool aForceDownLoad, PRBool aNewSession,
PRUint32 *aSession, char *aIdKey)
{
PRInt16 nResult = 0;
PRUint32 n_SessionId = 0;
PR_Lock(m_Lock);
// Check whether max sessions is exceeded
if (sessionCount >= m_nMaxSessions)
{
PR_Unlock(m_Lock);
return -1;
}
if (aUserName != nsnull && aUserName[0] != '\0')
{
nsStringKey usernameKey(aUserName);
n_SessionId = (PRUint32) m_ProfileMap.Get(&usernameKey);
}
// try to share a session; if not create a session
if (n_SessionId > 0)
{
nsPRUintKey sessionKey(n_SessionId);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp != nsnull)
{
pTemp->IncrementSession();
*aSession = n_SessionId;
nResult = 1;
}
}
else if (aNewSession || n_SessionId == 0) // checking for n_SessionId is a concession
{
// create a new session ; if new session is specified OR there is no session
nsMAPISession *pTemp = nsnull;
pTemp = new nsMAPISession(aHwnd, aUserName,
aPassword, aForceDownLoad, aIdKey);
if (pTemp != nsnull)
{
session_generator++;
// I don't think there will be (2 power 32) sessions alive
// in a cycle. This is an assumption
if (session_generator == 0)
session_generator++;
nsPRUintKey sessionKey(session_generator);
m_SessionMap.Put(&sessionKey, pTemp);
if (aUserName != nsnull && aUserName[0] != '\0')
{
nsStringKey usernameKey(aUserName);
m_ProfileMap.Put(&usernameKey, (void*)session_generator);
}
*aSession = session_generator;
sessionCount++;
nResult = 1;
}
}
PR_Unlock(m_Lock);
return nResult;
}
PRBool nsMAPIConfiguration::UnRegisterSession(PRUint32 aSessionID)
{
PRBool bResult = PR_FALSE;
PR_Lock(m_Lock);
if (aSessionID != 0)
{
nsPRUintKey sessionKey(aSessionID);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp != nsnull)
{
if (pTemp->DecrementSession() == 0)
{
if (pTemp->m_pProfileName.get() != nsnull)
{
nsStringKey stringKey(pTemp->m_pProfileName.get());
m_ProfileMap.Remove(&stringKey);
}
m_SessionMap.Remove(&sessionKey);
sessionCount--;
bResult = PR_TRUE;
}
}
}
PR_Unlock(m_Lock);
return bResult;
}
PRBool nsMAPIConfiguration::IsSessionValid(PRUint32 aSessionID)
{
if (aSessionID == 0)
return PR_FALSE;
PRBool retValue = PR_FALSE;
nsPRUintKey sessionKey(aSessionID);
PR_Lock(m_Lock);
retValue = m_SessionMap.Exists(&sessionKey);
PR_Unlock(m_Lock);
return retValue;
}
PRUnichar *nsMAPIConfiguration::GetPassword(PRUint32 aSessionID)
{
PRUnichar *pResult = nsnull;
PR_Lock(m_Lock);
if (aSessionID != 0)
{
nsPRUintKey sessionKey(aSessionID);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp)
{
pResult = pTemp->GetPassword();
}
}
PR_Unlock(m_Lock);
return pResult;
}
char *nsMAPIConfiguration::GetIdKey(PRUint32 aSessionID)
{
char *pResult = nsnull;
PR_Lock(m_Lock);
if (aSessionID != 0)
{
nsPRUintKey sessionKey(aSessionID);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp)
{
pResult = pTemp->GetIdKey();
}
}
PR_Unlock(m_Lock);
return pResult;
}
// util func
HRESULT nsMAPIConfiguration::GetMAPIErrorFromNSError (nsresult res)
{
HRESULT hr = SUCCESS_SUCCESS ;
if (NS_SUCCEEDED (hr)) return hr ;
// if failure return the related MAPI failure code
switch (res)
{
case NS_MSG_NO_RECIPIENTS :
hr = MAPI_E_BAD_RECIPTYPE ;
break ;
case NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS :
hr = MAPI_E_INVALID_RECIPS ;
break ;
case NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER :
hr = MAPI_E_LOGIN_FAILURE ;
break ;
case NS_MSG_UNABLE_TO_OPEN_FILE :
case NS_MSG_UNABLE_TO_OPEN_TMP_FILE :
case NS_MSG_COULDNT_OPEN_FCC_FOLDER :
case NS_ERROR_FILE_INVALID_PATH :
hr = MAPI_E_ATTACHMENT_OPEN_FAILURE ;
break ;
case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST :
hr = MAPI_E_ATTACHMENT_NOT_FOUND ;
break ;
case NS_MSG_CANCELLING :
hr = MAPI_E_USER_ABORT ;
break ;
case NS_MSG_ERROR_WRITING_FILE :
case NS_MSG_UNABLE_TO_SAVE_TEMPLATE :
case NS_MSG_UNABLE_TO_SAVE_DRAFT :
hr = MAPI_E_ATTACHMENT_WRITE_FAILURE ;
break ;
default :
hr = MAPI_E_FAILURE ;
break ;
}
return hr ;
}
nsMAPISession::nsMAPISession(PRUint32 aHwnd, const PRUnichar *aUserName,\
const PRUnichar *aPassword, \
PRBool aForceDownLoad, char *aKey)
: m_bIsForcedDownLoad(aForceDownLoad),
m_hAppHandle(aHwnd),
m_nShared(1),
m_pIdKey(aKey)
{
m_pProfileName.Assign(aUserName);
m_pPassword.Assign(aPassword);
}
nsMAPISession::~nsMAPISession()
{
if (m_pIdKey != nsnull)
{
delete [] m_pIdKey;
m_pIdKey = nsnull;
}
}
PRUint32 nsMAPISession::IncrementSession()
{
return ++m_nShared;
}
PRUint32 nsMAPISession::DecrementSession()
{
return --m_nShared;
}
PRUint32 nsMAPISession::GetSessionCount()
{
return m_nShared;
}
PRUnichar *nsMAPISession::GetPassword()
{
return (PRUnichar *)m_pPassword.get();
}
char *nsMAPISession::GetIdKey()
{
return m_pIdKey;
}

View File

@@ -0,0 +1,112 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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 ***** */
#ifndef MSG_MAPI_MAIN_H_
#define NSG_MAPI_MAIN_H_
#define MAX_NAME_LEN 256
#define MAX_PW_LEN 256
#define MAX_SESSIONS 50
#define MAPI_SENDCOMPLETE_EVENT "SendCompletionEvent"
#define MAPI_PROPERTIES_CHROME "chrome://messenger-mapi/locale/mapi.properties"
#define PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND "mapi.blind-send.warn"
#define PREF_MAPI_BLIND_SEND_ENABLED "mapi.blind-send.enabled"
#include "nsXPIDLString.h"
#include "nspr.h"
#include "nsString.h"
#include "nsHashtable.h"
class nsMAPIConfiguration
{
private :
static PRUint32 session_generator;
static PRUint32 sessionCount;
static nsMAPIConfiguration *m_pSelfRef;
PRLock *m_Lock;
PRUint32 m_nMaxSessions;
nsHashtable m_ProfileMap;
nsHashtable m_SessionMap;
nsMAPIConfiguration();
public :
static nsMAPIConfiguration *GetMAPIConfiguration();
void OpenConfiguration();
PRInt16 RegisterSession(PRUint32 aHwnd, const PRUnichar *aUserName, \
const PRUnichar *aPassword, PRBool aForceDownLoad, \
PRBool aNewSession, PRUint32 *aSession, char *aIdKey);
PRBool IsSessionValid(PRUint32 aSessionID);
PRBool UnRegisterSession(PRUint32 aSessionID);
PRUnichar *GetPassword(PRUint32 aSessionID);
char *GetIdKey(PRUint32 aSessionID);
~nsMAPIConfiguration();
// a util func
static HRESULT GetMAPIErrorFromNSError (nsresult res) ;
};
class nsMAPISession
{
friend class nsMAPIConfiguration;
private :
PRBool m_bIsForcedDownLoad;
PRBool m_bApp_or_Service;
PRUint32 m_hAppHandle;
PRUint32 m_nShared;
char *m_pIdKey;
nsString m_pProfileName;
nsString m_pPassword;
public :
nsMAPISession(PRUint32 aHwnd, const PRUnichar *aUserName, \
const PRUnichar *aPassword, \
PRBool aForceDownLoad, char *aKey);
PRUint32 IncrementSession();
PRUint32 DecrementSession();
PRUint32 GetSessionCount();
PRUnichar *nsMAPISession::GetPassword();
char *nsMAPISession::GetIdKey();
~nsMAPISession();
};
#endif // MSG_MAPI_MAIN_H_

View File

@@ -0,0 +1,209 @@
/* ***** 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
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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 ***** */
#include "nsCOMPtr.h"
#include "objbase.h"
#include "nsISupports.h"
#include "nsIGenericFactory.h"
#include "nsIObserverService.h"
#include "nsIAppStartupNotifier.h"
#include "nsIServiceManager.h"
#include "nsIComponentManager.h"
#include "nsICategoryManager.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIPrefBranchInternal.h"
#include "msgMapiSupport.h"
#include "nsMapiRegistryUtils.h"
#include "nsMapiRegistry.h"
#include "msgMapiImp.h"
/** Implementation of the nsIMapiSupport interface.
* Use standard implementation of nsISupports stuff.
*/
NS_IMPL_THREADSAFE_ISUPPORTS2(nsMapiSupport, nsIMapiSupport, nsIObserver);
static NS_METHOD nsMapiRegistrationProc(nsIComponentManager *aCompMgr,
nsIFile *aPath, const char *registryLocation, const char *componentType,
const nsModuleComponentInfo *info)
{
nsresult rv;
nsCOMPtr<nsICategoryManager> categoryManager(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv))
rv = categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY, "Mapi Support",
"service," NS_IMAPISUPPORT_CONTRACTID, PR_TRUE, PR_TRUE, nsnull);
return rv ;
}
NS_IMETHODIMP
nsMapiSupport::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
{
nsresult rv = NS_OK ;
if (!nsCRT::strcmp(aTopic, "profile-after-change"))
return InitializeMAPISupport();
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
return ShutdownMAPISupport();
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID))
{
nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject, &rv);
if (NS_FAILED(rv)) return rv;
// which preference changed?
if (!nsCRT::strcmp(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, NS_ConvertUCS2toUTF8(aData).get()))
{
PRBool bIsDefault = PR_FALSE ;
rv = prefs->GetBoolPref(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, &bIsDefault);
if (NS_FAILED(rv)) return rv;
nsCOMPtr <nsIMapiRegistry> mapiRegistry = do_CreateInstance(NS_IMAPIREGISTRY_CONTRACTID, &rv) ;
if (NS_FAILED(rv)) return rv;
return mapiRegistry->SetIsDefaultMailClient(bIsDefault) ;
}
return rv ;
}
nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1", &rv));
if (NS_FAILED(rv)) return rv;
rv = observerService->AddObserver(this,"profile-after-change", PR_FALSE);
if (NS_FAILED(rv)) return rv;
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIPrefBranchInternal> prefInternal = do_QueryInterface(prefs, &rv);
if (NS_FAILED(rv)) return rv;
rv = prefInternal->AddObserver(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, this, PR_FALSE);
if (NS_FAILED(rv)) return rv;
return rv;
}
nsMapiSupport::nsMapiSupport()
: m_dwRegister(0),
m_nsMapiFactory(nsnull)
{
NS_INIT_ISUPPORTS();
}
nsMapiSupport::~nsMapiSupport()
{
}
NS_IMETHODIMP
nsMapiSupport::InitializeMAPISupport()
{
::CoInitialize(nsnull) ;
if (m_nsMapiFactory == nsnull) // No Registering if already done. Sanity Check!!
{
m_nsMapiFactory = new CMapiFactory();
if (m_nsMapiFactory != nsnull)
{
HRESULT hr = ::CoRegisterClassObject(CLSID_CMapiImp, \
m_nsMapiFactory, \
CLSCTX_LOCAL_SERVER, \
REGCLS_MULTIPLEUSE, \
&m_dwRegister);
if (FAILED(hr))
{
m_nsMapiFactory->Release() ;
m_nsMapiFactory = nsnull;
return NS_ERROR_FAILURE;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMapiSupport::ShutdownMAPISupport()
{
if (m_dwRegister != 0)
::CoRevokeClassObject(m_dwRegister);
if (m_nsMapiFactory != nsnull)
{
m_nsMapiFactory->Release();
m_nsMapiFactory = nsnull;
}
::CoUninitialize();
return NS_OK ;
}
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiRegistry);
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiSupport);
// The list of components we register
static nsModuleComponentInfo components[] =
{
{
NS_IMAPIREGISTRY_CLASSNAME,
NS_IMAPIREGISTRY_CID,
NS_IMAPIREGISTRY_CONTRACTID,
nsMapiRegistryConstructor
},
{
NS_IMAPISUPPORT_CLASSNAME,
NS_IMAPISUPPORT_CID,
NS_IMAPISUPPORT_CONTRACTID,
nsMapiSupportConstructor,
nsMapiRegistrationProc,
nsnull
}
};
NS_IMPL_NSGETMODULE(msgMapiModule, components);

View File

@@ -11,14 +11,14 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* The Initial Developer of the Original Code is
# Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@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
@@ -34,23 +34,33 @@
*
* ***** END LICENSE BLOCK ***** */
/* Library identity and versioning */
#ifndef MSG_MAPI_SUPPORT_H_
#define MSG_MAPI_SUPPORT_H_
#include "softkver.h"
#include "nsIObserver.h"
#include "nsIMapiSupport.h"
#include "msgMapiFactory.h"
#if defined(DEBUG)
#define _DEBUG_STRING " (debug)"
#else
#define _DEBUG_STRING ""
#endif
#define NS_IMAPISUPPORT_CID \
{0x8967fed2, 0xc8bb, 0x11d5, \
{ 0xa3, 0xe9, 0x00, 0xb0, 0xd0, 0xf3, 0xba, 0xa7 }}
/*
* Version information for the 'ident' and 'what commands
*
* NOTE: the first component of the concatenated rcsid string
* must not end in a '$' to prevent rcs keyword substitution.
*/
const char __nss_freebl_rcsid[] = "$Header: NSS " SOFTOKEN_VERSION _DEBUG_STRING
" " __DATE__ " " __TIME__ " $";
const char __nss_freebl_sccsid[] = "@(#)NSS " SOFTOKEN_VERSION _DEBUG_STRING
" " __DATE__ " " __TIME__;
class nsMapiSupport : public nsIMapiSupport,
public nsIObserver
{
public :
nsMapiSupport();
~nsMapiSupport();
// Declare all interface methods we must implement.
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIMAPISUPPORT
private :
DWORD m_dwRegister;
CMapiFactory *m_nsMapiFactory;
};
#endif // MSG_MAPI_SUPPORT_H_

View File

@@ -0,0 +1,167 @@
/* ***** 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) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@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 ***** */
#include "nsIServiceManager.h"
#include "nsXPIDLString.h"
#include "nsIPromptService.h"
#include "nsIProxyObjectManager.h"
#include "nsProxiedService.h"
#include "nsMapiRegistryUtils.h"
#include "nsMapiRegistry.h"
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
/** Implementation of the nsIMapiRegistry interface.
* Use standard implementation of nsISupports stuff.
*/
NS_IMPL_ISUPPORTS1(nsMapiRegistry, nsIMapiRegistry);
nsMapiRegistry::nsMapiRegistry() {
NS_INIT_ISUPPORTS();
m_ShowDialog = ! m_registryUtils.verifyRestrictedAccess();
m_DefaultMailClient = m_registryUtils.IsDefaultMailClient();
}
nsMapiRegistry::~nsMapiRegistry() {
}
NS_IMETHODIMP
nsMapiRegistry::GetIsDefaultMailClient(PRBool * retval) {
// we need to get the value from registry everytime
// because the registry settings can be changed from
// other mail applications.
*retval = m_registryUtils.IsDefaultMailClient();
return NS_OK;
}
NS_IMETHODIMP
nsMapiRegistry::GetShowDialog(PRBool * retval) {
*retval = m_ShowDialog;
return NS_OK;
}
NS_IMETHODIMP
nsMapiRegistry::SetIsDefaultMailClient(PRBool aIsDefaultMailClient)
{
nsresult rv = NS_OK ;
if (aIsDefaultMailClient)
{
rv = m_registryUtils.setDefaultMailClient();
if (NS_SUCCEEDED(rv))
m_DefaultMailClient = PR_TRUE;
else
m_registryUtils.ShowMapiErrorDialog();
}
else
{
rv = m_registryUtils.unsetDefaultMailClient();
if (NS_SUCCEEDED(rv))
m_DefaultMailClient = PR_FALSE;
else
m_registryUtils.ShowMapiErrorDialog();
}
return rv ;
}
/** This will bring up the dialog box only once per session and
* only if the current app is not default Mail Client.
* This also checks the registry if the registry key
* showMapiDialog is set
*/
NS_IMETHODIMP
nsMapiRegistry::ShowMailIntegrationDialog(nsIDOMWindow *aParentWindow) {
nsresult rv;
if (!m_ShowDialog || !m_registryUtils.getShowDialog()) return NS_OK;
nsCOMPtr<nsIPromptService> promptService(do_GetService(
"@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_SUCCEEDED(rv) && promptService)
{
nsCOMPtr<nsIStringBundle> bundle;
rv = m_registryUtils.MakeMapiStringBundle (getter_AddRefs (bundle)) ;
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogTitle;
const PRUnichar *brandStrings[] = { m_registryUtils.brandName() };
NS_NAMED_LITERAL_STRING(dialogTitlePropertyTag, "dialogTitle");
rv = bundle->FormatStringFromName(dialogTitlePropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogTitle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogText;
NS_NAMED_LITERAL_STRING(dialogTextPropertyTag, "dialogText");
rv = bundle->FormatStringFromName(dialogTextPropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogText));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString checkboxText;
rv = bundle->GetStringFromName(
NS_LITERAL_STRING("checkboxText").get(),
getter_Copies(checkboxText));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
PRBool checkValue = PR_FALSE;
PRInt32 buttonPressed = 0;
rv = promptService->ConfirmEx(aParentWindow,
dialogTitle,
dialogText.get(),
(nsIPromptService::BUTTON_TITLE_YES *
nsIPromptService::BUTTON_POS_0) +
(nsIPromptService::BUTTON_TITLE_NO *
nsIPromptService::BUTTON_POS_1),
nsnull,
nsnull,
nsnull,
checkboxText,
&checkValue,
&buttonPressed);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = m_registryUtils.SetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
"showMapiDialog", (checkValue) ? "0" : "1");
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
m_ShowDialog = PR_FALSE;
if (!buttonPressed)
rv = SetIsDefaultMailClient(PR_TRUE) ; // SetDefaultMailClient();
}
return rv;
}

View File

@@ -0,0 +1,76 @@
/* ***** 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) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@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 ***** */
#ifndef nsmapiregistry_h____
#define nsmapiregistry_h____
#include "nsIMapiRegistry.h"
#ifndef MAX_BUF
#define MAX_BUF 4096
#endif
/* c5be14ba-4e0a-4eec-a1b8-04363761d63c */
#define NS_IMAPIREGISTRY_CID \
{ 0xc5be14ba, 0x4e0a, 0x4eec, {0xa1, 0xb8, 0x04, 0x36, 0x37, 0x61, 0xd6, 0x3c} }
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
#define MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT "mailnews.default_mail_client"
class nsMapiRegistry : public nsIMapiRegistry {
public:
// ctor/dtor
nsMapiRegistry();
virtual ~nsMapiRegistry();
// Declare all interface methods we must implement.
NS_DECL_ISUPPORTS
NS_DECL_NSIMAPIREGISTRY
protected:
PRBool m_DefaultMailClient;
PRBool m_ShowDialog;
nsMapiRegistryUtils m_registryUtils ;
private:
// Special member to handle initialization.
PRBool mHaveBeenSet;
}; // nsMapiRegistry
#endif // nsmapiregistry_h____

View File

@@ -0,0 +1,743 @@
/* ***** 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) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@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 ***** */
#undef UNICODE
#undef _UNICODE
#include "nsIServiceManager.h"
#include "msgMapiImp.h"
#include "msgMapiMain.h"
#include "nsMapiRegistryUtils.h"
#include "nsString.h"
#include "nsIStringBundle.h"
#include "nsIPromptService.h"
#include "nsXPIDLString.h"
#include "nsSpecialSystemDirectory.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIPref.h"
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
#define EXE_EXTENSION ".exe"
#define USERAGENT_VERSION_PREF "general.useragent.misc"
#define USERAGENT_VERSION_NS_PREF "general.useragent.vendorSub"
#define USERAGENT_PREF_PREFIX "rv:"
nsMapiRegistryUtils::nsMapiRegistryUtils()
{
m_mapiStringBundle = nsnull ;
}
const char * nsMapiRegistryUtils::thisApplication()
{
if (m_thisApp.IsEmpty()) {
char buffer[MAX_PATH] = {0};
DWORD len = ::GetModuleFileName(NULL, buffer, MAX_PATH);
if (!len) return nsnull ;
char shortPathBuf[MAX_PATH] = {0};
len = ::GetShortPathName(buffer, shortPathBuf, MAX_PATH);
if (!len) return nsnull ;
m_thisApp = buffer;
m_thisApp.ToUpperCase();
}
return m_thisApp.get() ;
}
const PRUnichar * nsMapiRegistryUtils::brandName()
{
nsresult rv;
if (m_brand.IsEmpty()) {
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(
kStringBundleServiceCID, &rv));
if (NS_SUCCEEDED(rv) && bundleService) {
nsCOMPtr<nsIStringBundle> brandBundle;
rv = bundleService->CreateBundle(
"chrome://global/locale/brand.properties",
getter_AddRefs(brandBundle));
if (NS_SUCCEEDED(rv)) {
nsXPIDLString brandName;
rv = brandBundle->GetStringFromName(
NS_LITERAL_STRING("brandShortName").get(),
getter_Copies(brandName));
if (NS_SUCCEEDED(rv)) {
m_brand = brandName ;
}
}
}
}
return m_brand.get() ;
}
const PRUnichar * nsMapiRegistryUtils::versionNo()
{
if (!m_versionNo.IsEmpty())
return m_versionNo.get() ;
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
if (prefs) {
nsXPIDLCString versionStr ;
nsresult rv = prefs->GetCharPref(USERAGENT_VERSION_NS_PREF, getter_Copies(versionStr));
if (NS_SUCCEEDED(rv) && versionStr)
m_versionNo.AssignWithConversion (versionStr.get()) ;
else {
rv = prefs->GetCharPref(USERAGENT_VERSION_PREF, getter_Copies(versionStr));
if (NS_SUCCEEDED(rv) && versionStr) {
m_versionNo.AssignWithConversion (versionStr.get()) ;
m_versionNo.StripChars (USERAGENT_PREF_PREFIX) ;
}
}
}
return m_versionNo.get() ;
}
PRBool nsMapiRegistryUtils::verifyRestrictedAccess() {
char subKey[] = "Software\\Mozilla - Test Key";
PRBool result = PR_FALSE;
DWORD dwDisp = 0;
HKEY key;
// Try to create/open a subkey under HKLM.
DWORD rc = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
subKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&key,
&dwDisp);
if (rc == ERROR_SUCCESS) {
// Key was opened; first close it.
::RegCloseKey(key);
// Delete it if we just created it.
switch(dwDisp) {
case REG_CREATED_NEW_KEY:
::RegDeleteKey(HKEY_LOCAL_MACHINE, subKey);
break;
case REG_OPENED_EXISTING_KEY:
break;
}
} else {
// Can't create/open it; we don't have access.
result = PR_TRUE;
}
return result;
}
nsresult nsMapiRegistryUtils::SetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, char * value)
{
nsresult result = NS_ERROR_FAILURE;
HKEY key;
LONG rc = ::RegCreateKey(baseKey, keyName, &key);
if (rc == ERROR_SUCCESS) {
rc = ::RegSetValueEx(key, valueName, NULL, REG_SZ,
(LPBYTE)(const char*)value, strlen(value));
if (rc == ERROR_SUCCESS) {
result = NS_OK;
}
::RegCloseKey(key);
}
return result;
}
nsresult nsMapiRegistryUtils::DeleteRegistryValue(HKEY baseKey, const char * keyName,
const char * valueName)
{
nsresult result = NS_ERROR_FAILURE;
HKEY key;
LONG rc = ::RegOpenKey(baseKey, keyName, &key);
if (rc == ERROR_SUCCESS) {
rc = ::RegDeleteValue(key, valueName);
if (rc == ERROR_SUCCESS)
result = NS_OK;
::RegCloseKey(key);
}
return result;
}
void nsMapiRegistryUtils::GetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, nsCAutoString & value)
{
HKEY key;
LONG rc = ::RegOpenKey(baseKey, keyName, &key);
if (rc == ERROR_SUCCESS) {
char buffer[MAX_PATH] = {0};
DWORD len = sizeof buffer;
rc = ::RegQueryValueEx(key, valueName, NULL, NULL,
(LPBYTE)buffer, &len);
if (rc == ERROR_SUCCESS) {
if (len)
value = buffer;
}
::RegCloseKey(key);
}
}
PRBool nsMapiRegistryUtils::IsDefaultMailClient()
{
if (!isSmartDll() && !isMozDll())
return PR_FALSE;
nsCAutoString name;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Clients\\Mail", "", name);
if (!name.IsEmpty()) {
nsCAutoString keyName("Software\\Clients\\Mail\\");
keyName += name.get();
keyName += "\\protocols\\mailto\\shell\\open\\command";
nsCAutoString result;
GetRegistryKey(HKEY_LOCAL_MACHINE, keyName.get(), "", result);
if (!result.IsEmpty()) {
nsCAutoString strExtension;
strExtension.Assign(EXE_EXTENSION);
result.ToUpperCase();
strExtension.ToUpperCase();
PRInt32 index = result.RFind(strExtension.get());
if (index != kNotFound) {
result.Truncate(index + strExtension.Length());
}
nsCAutoString thisApp (thisApplication()) ;
return (result == thisApp);
}
}
return PR_FALSE;
}
nsresult nsMapiRegistryUtils::saveDefaultMailClient()
{
nsresult rv;
nsCAutoString name ;
GetRegistryKey(HKEY_LOCAL_MACHINE,"Software\\Clients\\Mail", "", name);
if (!name.IsEmpty()) {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail",
(char *)name.get());
if (NS_SUCCEEDED(rv)) {
nsCAutoString keyName("Software\\Clients\\Mail\\");
keyName += name.get();
keyName += "\\protocols\\mailto\\shell\\open\\command";
nsCAutoString appPath ;
GetRegistryKey(HKEY_LOCAL_MACHINE, keyName.get(), "", appPath);
if (!appPath.IsEmpty()) {
nsCAutoString stringName("HKEY_LOCAL_MACHINE\\");
stringName += keyName.get();
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
stringName.get(), (char *)appPath.get());
}
}
}
else
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail",
"");
return rv;
}
nsresult nsMapiRegistryUtils::saveUserDefaultMailClient()
{
nsresult rv;
nsCAutoString name ;
GetRegistryKey(HKEY_CURRENT_USER,"Software\\Clients\\Mail", "", name);
if (!name.IsEmpty()) {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_CURRENT_USER\\Software\\Clients\\Mail",
(char *)name.get());
}
else {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_CURRENT_USER\\Software\\Clients\\Mail",
"");
}
return rv;
}
/**
* Check whether it is a smart dll or not. Smart dll is the one installed by
* IE5 or Outlook Express which forwards the MAPI calls to the dll based on the
* registry key setttings.
* Returns TRUE if is a smart dll.
*/
typedef HRESULT (FAR PASCAL GetOutlookVersionFunc)();
PRBool nsMapiRegistryUtils::isSmartDll()
{
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return PR_FALSE;
PL_strcatn(buffer, sizeof(buffer), "\\Mapi32.dll");
HINSTANCE hInst;
GetOutlookVersionFunc *doesExist = nsnull;
hInst = LoadLibrary(buffer);
if (hInst == nsnull)
return PR_FALSE;
doesExist = (GetOutlookVersionFunc *) GetProcAddress (hInst, "GetOutlookVersion");
FreeLibrary(hInst);
return (doesExist != nsnull);
}
typedef HRESULT (FAR PASCAL GetMapiDllVersion)();
/**
* Checks whether mapi32.dll is installed by this app.
* Returns TRUE if it is.
*/
PRBool nsMapiRegistryUtils::isMozDll()
{
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return PR_FALSE;
PL_strcatn(buffer, sizeof(buffer), "\\Mapi32.dll");
HINSTANCE hInst;
GetMapiDllVersion *doesExist = nsnull;
hInst = LoadLibrary(buffer);
if (hInst == nsnull)
return PR_FALSE;
doesExist = (GetMapiDllVersion *) GetProcAddress (hInst, "GetMapiDllVersion");
FreeLibrary(hInst);
return (doesExist != nsnull);
}
/** Renames Mapi32.dl in system directory to Mapi32_moz_bak.dll
* copies the mozMapi32.dll from bin directory to the system directory
*/
nsresult nsMapiRegistryUtils::CopyMozMapiToWinSysDir()
{
nsresult rv;
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return NS_ERROR_FAILURE;
nsCAutoString filePath(buffer);
filePath.Append("\\Mapi32_moz_bak.dll");
nsCOMPtr<nsILocalFile> pCurrentMapiFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !pCurrentMapiFile) return rv;
pCurrentMapiFile->InitWithPath(filePath.get());
nsCOMPtr<nsIFile> pMozMapiFile;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (!directoryService) return NS_ERROR_FAILURE;
rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(pMozMapiFile));
if (NS_FAILED(rv)) return rv;
pMozMapiFile->Append("mozMapi32.dll");
PRBool bExist;
rv = pMozMapiFile->Exists(&bExist);
if (NS_FAILED(rv) || !bExist) return rv;
rv = pCurrentMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist)
{
rv = pCurrentMapiFile->Remove(PR_FALSE);
}
if (NS_FAILED(rv)) return rv;
filePath.Assign(buffer);
filePath.Append("\\Mapi32.dll");
pCurrentMapiFile->InitWithPath(filePath.get());
rv = pCurrentMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist)
{
rv = pCurrentMapiFile->MoveTo(nsnull, "Mapi32_moz_bak.dll");
if (NS_FAILED(rv)) return rv;
nsCAutoString fullFilePath(buffer);
fullFilePath.Append("\\Mapi32_moz_bak.dll");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"Mapi_backup_dll",
(char *)fullFilePath.get());
if (NS_FAILED(rv)) {
RestoreBackedUpMapiDll();
return rv;
}
}
NS_NAMED_LITERAL_STRING(fileName, "Mapi32.dll");
filePath.Assign(buffer);
pCurrentMapiFile->InitWithPath(filePath.get());
rv = pMozMapiFile->CopyToUnicode(pCurrentMapiFile, fileName.get());
if (NS_FAILED(rv))
RestoreBackedUpMapiDll();
return rv;
}
/** deletes the Mapi32.dll in system directory and renames Mapi32_moz_bak.dll
* to Mapi32.dll
*/
nsresult nsMapiRegistryUtils::RestoreBackedUpMapiDll()
{
nsresult rv;
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return NS_ERROR_FAILURE;
nsCAutoString filePath(buffer);
nsCAutoString previousFileName(buffer);
filePath.Append("\\Mapi32.dll");
previousFileName.Append("\\Mapi32_moz_bak.dll");
nsCOMPtr <nsILocalFile> pCurrentMapiFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !pCurrentMapiFile) return NS_ERROR_FAILURE;
pCurrentMapiFile->InitWithPath(filePath.get());
nsCOMPtr<nsILocalFile> pPreviousMapiFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !pPreviousMapiFile) return NS_ERROR_FAILURE;
pPreviousMapiFile->InitWithPath(previousFileName.get());
PRBool bExist;
rv = pCurrentMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist) {
rv = pCurrentMapiFile->Remove(PR_FALSE);
if (NS_FAILED(rv)) return rv;
}
rv = pPreviousMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist)
rv = pPreviousMapiFile->MoveTo(nsnull, "Mapi32.dll");
if (NS_SUCCEEDED(rv))
DeleteRegistryValue(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"Mapi_backup_dll");
return rv;
}
/** Sets Mozilla as default Mail Client
*/
nsresult nsMapiRegistryUtils::setDefaultMailClient()
{
nsresult rv;
nsresult mailKeySet=NS_ERROR_FAILURE;
if (verifyRestrictedAccess()) return NS_ERROR_FAILURE;
if (!isSmartDll()) {
if (NS_FAILED(CopyMozMapiToWinSysDir())) return NS_ERROR_FAILURE;
}
rv = saveDefaultMailClient();
if (NS_FAILED(saveUserDefaultMailClient()) ||
NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCAutoString keyName("Software\\Clients\\Mail\\");
nsCAutoString appName (NS_ConvertUCS2toUTF8(brandName()).get());
if (!appName.IsEmpty()) {
keyName.Append(appName.get());
nsCOMPtr<nsIStringBundle> bundle;
rv = MakeMapiStringBundle (getter_AddRefs (bundle)) ;
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString defaultMailTitle;
const PRUnichar *keyValuePrefixStr[] = { brandName(), versionNo() };
NS_NAMED_LITERAL_STRING(defaultMailTitleTag, "defaultMailDisplayTitle");
rv = bundle->FormatStringFromName(defaultMailTitleTag.get(),
keyValuePrefixStr, 2,
getter_Copies(defaultMailTitle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(defaultMailTitle).get()) ) ;
}
else
rv = NS_ERROR_FAILURE;
if (NS_SUCCEEDED(rv)) {
nsCAutoString thisApp (thisApplication()) ;
if (NS_FAILED(rv)) return rv ;
nsCAutoString dllPath (thisApp) ;
PRInt32 index = dllPath.RFind("\\");
if (index != kNotFound)
dllPath.Truncate(index + 1);
dllPath += "mozMapi32.dll";
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(), "DLLPath",
(char *)dllPath.get());
if (NS_SUCCEEDED(rv)) {
keyName.Append("\\protocols\\mailto");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", "URL:MailTo Protocol");
if (NS_SUCCEEDED(rv)) {
nsCAutoString appPath (thisApp);
appPath += " \"%1\"";
keyName.Append("\\shell\\open\\command");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", (char *)appPath.get());
if (NS_SUCCEEDED(rv)) {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Clients\\Mail",
"", (char *)appName.get());
}
if (NS_SUCCEEDED(rv)) {
nsCAutoString mailAppPath(thisApp);
mailAppPath += " -mail";
nsCAutoString appKeyName ("Software\\Clients\\Mail\\");
appKeyName.Append(appName.get());
appKeyName.Append("\\shell\\open\\command");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
appKeyName.get(),
"", (char *)mailAppPath.get());
}
if (NS_SUCCEEDED(rv)) {
nsCAutoString iconPath(thisApp);
iconPath += ",0";
nsCAutoString iconKeyName ("Software\\Clients\\Mail\\");
iconKeyName.Append(appName.get());
iconKeyName.Append("\\DefaultIcon");
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
iconKeyName.get(),
"", (char *)iconPath.get());
}
}
}
}
if (NS_SUCCEEDED(mailKeySet)) {
nsresult desktopKeySet = SetRegistryKey(HKEY_CURRENT_USER,
"Software\\Clients\\Mail",
"", (char *)appName.get());
if (NS_SUCCEEDED(desktopKeySet)) {
desktopKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", "1");
}
::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
(LPARAM)"Software\\Clients\\Mail");
RegisterServer(CLSID_CMapiImp, "Mozilla MAPI", "mozMapi", "mozMapi.1");
return desktopKeySet;
}
return mailKeySet;
}
/** Removes Mozilla as the default Mail client and restores the previous setting
*/
nsresult nsMapiRegistryUtils::unsetDefaultMailClient() {
nsresult result = NS_OK;
nsresult mailKeySet = NS_ERROR_FAILURE;
if (verifyRestrictedAccess()) return NS_ERROR_FAILURE;
if (!isSmartDll()) {
if (NS_FAILED(RestoreBackedUpMapiDll())) return NS_ERROR_FAILURE;
}
nsCAutoString name ;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail", name);
nsCAutoString appName (NS_ConvertUCS2toUTF8(brandName()).get());
if (!name.IsEmpty() && !appName.IsEmpty() && name.Equals(appName)) {
nsCAutoString keyName("HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail\\");
keyName.Append(appName.get());
keyName.Append("\\protocols\\mailto\\shell\\open\\command");
nsCAutoString appPath ;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
keyName.get(), appPath);
if (!appPath.IsEmpty()) {
keyName.Assign("Software\\Clients\\Mail\\");
keyName.Append(appName.get());
keyName.Append("\\protocols\\mailto\\shell\\open\\command");
result = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", (char *)appPath.get());
if (NS_SUCCEEDED(result)) {
PRInt32 index = appPath.RFind("\\");
if (index != kNotFound)
appPath.Truncate(index + 1);
appPath += "mozMapi32.dll";
keyName.Assign("Software\\Clients\\Mail\\");
keyName.Append(appName.get());
result = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"DLLPath", (char *) appPath.get());
}
}
}
if (!name.IsEmpty()) {
if (NS_SUCCEEDED(result)) {
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Clients\\Mail",
"", (char *)name.get());
}
}
else
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Clients\\Mail",
"", "");
if (NS_SUCCEEDED(mailKeySet)) {
nsCAutoString userAppName ;
GetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_CURRENT_USER\\Software\\Clients\\Mail", userAppName);
nsresult desktopKeySet = NS_OK;
if (!userAppName.IsEmpty()) {
desktopKeySet = SetRegistryKey(HKEY_CURRENT_USER,
"Software\\Clients\\Mail",
"", (char *)userAppName.get());
}
else {
DeleteRegistryValue(HKEY_CURRENT_USER, "Software\\Clients\\Mail", "");
}
if (NS_SUCCEEDED(desktopKeySet)) {
desktopKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", "0");
}
::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
(LPARAM)"Software\\Clients\\Mail");
UnregisterServer(CLSID_CMapiImp, "mozMapi", "mozMapi.1");
return desktopKeySet;
}
return mailKeySet;
}
/** Returns FALSE if showMapiDialog is set to 0.
* Returns TRUE otherwise
* Also returns TRUE if the Mozilla has been set as the default mail client
* and some other application has changed that setting.
* This function gets called only if the current app is not the default mail
* client
*/
PRBool nsMapiRegistryUtils::getShowDialog() {
PRBool rv = PR_FALSE;
nsCAutoString showDialog ;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
"showMapiDialog", showDialog);
// if the user has not selected the checkbox, show dialog
if (showDialog.IsEmpty() || showDialog.Equals("1"))
rv = PR_TRUE;
if (!rv) {
// even if the user has selected the checkbox
// show it if some other application has changed the
// default setting.
nsCAutoString setMailDefault ;
GetRegistryKey(HKEY_LOCAL_MACHINE,"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", setMailDefault);
if (setMailDefault.Equals("1")) {
// need to reset the defaultMailHasBeenSet to "0"
// so that after the dialog is displayed once,
// we do not keep displaying this dialog after the user has
// selected the checkbox
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", "0");
rv = PR_TRUE;
}
}
return rv;
}
nsresult nsMapiRegistryUtils::MakeMapiStringBundle(nsIStringBundle ** aMapiStringBundle)
{
nsresult rv = NS_OK ;
if (m_mapiStringBundle)
{
*aMapiStringBundle = m_mapiStringBundle ;
NS_ADDREF(*aMapiStringBundle);
return rv ;
}
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(
kStringBundleServiceCID, &rv));
if (NS_FAILED(rv) || !bundleService) return NS_ERROR_FAILURE;
rv = bundleService->CreateBundle(
MAPI_PROPERTIES_CHROME,
getter_AddRefs(m_mapiStringBundle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
NS_ADDREF(*aMapiStringBundle = m_mapiStringBundle) ;
return rv ;
}
nsresult nsMapiRegistryUtils::ShowMapiErrorDialog()
{
nsresult rv;
nsCOMPtr<nsIPromptService> promptService(do_GetService(
"@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_SUCCEEDED(rv) && promptService)
{
nsCOMPtr<nsIStringBundle> bundle;
rv = MakeMapiStringBundle (getter_AddRefs (bundle)) ;
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogTitle;
const PRUnichar *brandStrings[] = { brandName() };
NS_NAMED_LITERAL_STRING(dialogTitlePropertyTag, "errorMessageTitle");
rv = bundle->FormatStringFromName(dialogTitlePropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogTitle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogText;
NS_NAMED_LITERAL_STRING(dialogTextPropertyTag, "errorMessage");
rv = bundle->FormatStringFromName(dialogTextPropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogText));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = promptService->Alert(nsnull, dialogTitle,
dialogText);
}
return rv;
}

View File

@@ -0,0 +1,112 @@
/* ***** 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) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@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 ***** */
#ifndef nsmapiregistryutils_h____
#define nsmapiregistryutils_h____
#include <windows.h>
#include <string.h>
#include <winreg.h>
#include "Registry.h"
#include "nsString.h"
#include "nsIStringBundle.h"
class nsMapiRegistryUtils
{
private :
nsCAutoString m_thisApp ;
nsAutoString m_brand ;
nsAutoString m_versionNo ;
nsCOMPtr<nsIStringBundle> m_mapiStringBundle ;
public :
nsMapiRegistryUtils() ;
// returns TRUE if the Mapi32.dll is smart dll.
PRBool isSmartDll();
// returns TRUE if the Mapi32.dll is a Mozilla dll.
PRBool isMozDll();
// Returns the (fully-qualified) name of this executable.
const char * thisApplication() ;
// This returns the brand name for this application
const PRUnichar * brandName() ;
// This returns the version no for this application
const PRUnichar * versionNo() ;
// verifyRestrictedAccess - Returns PR_TRUE if this user only has restricted access
// to the registry keys we need to modify.
PRBool verifyRestrictedAccess() ;
// set the Windows registry key
nsresult SetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, char * value);
// delete a registry key
nsresult DeleteRegistryValue(HKEY baseKey, const char * keyName,
const char * valueName);
// get a Windows registry key
void GetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, nsCAutoString & value) ;
// Returns TRUE if the current application is default mail client.
PRBool IsDefaultMailClient();
// Sets Mozilla as default Mail Client
nsresult setDefaultMailClient() ;
// Removes Mozilla as the default Mail client and restores the previous setting
nsresult unsetDefaultMailClient() ;
// Saves the current setting of the default Mail Client in
// HKEY_LOCAL_MACHINE\\Software\\Mozilla\\Desktop
nsresult saveDefaultMailClient();
// Saves the current user setting of the default Mail Client in
// HKEY_LOCAL_MACHINE\\Software\\Mozilla\\Desktop
nsresult saveUserDefaultMailClient();
nsresult CopyMozMapiToWinSysDir();
nsresult RestoreBackedUpMapiDll();
// Returns FALSE if showMapiDialog is set to 0.
PRBool getShowDialog() ;
// create a string bundle for MAPI messages
nsresult MakeMapiStringBundle(nsIStringBundle ** aMapiStringBundle) ;
// display an error dialog for MAPI messages
nsresult ShowMapiErrorDialog() ;
} ;
#endif

View File

@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the packages being supplied by this jar -->
<RDF:Seq about="urn:mozilla:package:root">
<RDF:li resource="urn:mozilla:package:messenger-mapi"/>
</RDF:Seq>
<!-- package information -->
<RDF:Description about="urn:mozilla:package:messenger-mapi"
chrome:displayName="Messenger"
chrome:author="mozilla.org"
chrome:name="messenger-mapi"
chrome:localeVersion="0.9.7"
chrome:skinVersion="0.9.4">
</RDF:Description>
<!-- overlay information -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li resource="chrome://messenger/content/pref-mailnews.xul"/>
</RDF:Seq>
<!-- mapi items for Mail And Newsgroups preferences pane -->
<RDF:Seq about="chrome://messenger/content/pref-mailnews.xul">
<RDF:li>chrome://messenger-mapi/content/pref-mailnewsOverlay.xul</RDF:li>
</RDF:Seq>
</RDF:RDF>

View File

@@ -0,0 +1,3 @@
messenger.jar:
content/messenger-mapi/pref-mailnewsOverlay.xul
content/messenger-mapi/contents.rdf

View File

@@ -0,0 +1,29 @@
#!nmake
#
# 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 Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)\config\rules.mak>
chrome::
$(REGCHROME) content messenger-mapi messenger.jar

View File

@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:chrome="http://www.mozilla.org/rdf/chrome#"
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<!-- mapi items for mailnews preferences -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li resource="chrome://messenger/content/pref-mailnews.xul"/>
</RDF:Seq>
<RDF:Seq about="chrome://messenger/content/pref-mailnews.xul">
<RDF:li>chrome://messenger/content/pref-mailnewsOverlay.xul</RDF:li>
</RDF:Seq>
</RDF:RDF>

View File

@@ -0,0 +1,104 @@
/*
* 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 Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*/
function mailnewsOverlayStartup() {
mailnewsOverlayInit();
parent.hPrefWindow.registerOKCallbackFunc(onOK);
if (!("mapiPref" in parent)) {
parent.mapiPref = new Object;
parent.mapiPref.isDefaultMailClient =
document.getElementById("mailnewsEnableMapi").checked;
}
else {
// when we switch between different panes
// set the checkbox based on the saved state
var mailnewsEnableMapi = document.getElementById("mailnewsEnableMapi");
if (parent.mapiPref.isDefaultMailClient)
mailnewsEnableMapi.setAttribute("checked", "true");
else
mailnewsEnableMapi.setAttribute("checked", "false");
}
}
function mailnewsOverlayInit() {
try {
var mapiRegistry = Components.classes[ "@mozilla.org/mapiregistry;1" ].
getService( Components.interfaces.nsIMapiRegistry );
}
catch(ex){
mapiRegistry = null;
}
const prefbase = "system.windows.lock_ui.";
var mailnewsEnableMapi = document.getElementById("mailnewsEnableMapi");
if (mapiRegistry) {
// initialise preference component.
// While the data is coming from the system registry, we use a set
// of parallel preferences to indicate if the ui should be locked.
try {
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService()
.QueryInterface(Components.interfaces.nsIPrefService);
var prefBranch = prefService.getBranch(prefbase);
if (prefBranch && prefBranch.prefIsLocked("default_mail_client")) {
if (prefBranch.getBoolPref("default_mail_client"))
mapiRegistry.setDefaultMailClient();
else
mapiRegistry.unsetDefaultMailClient();
mailnewsEnableMapi.setAttribute("disabled", "true");
}
}
catch(ex) {}
if (mapiRegistry.isDefaultMailClient)
mailnewsEnableMapi.setAttribute("checked", "true");
else
mailnewsEnableMapi.setAttribute("checked", "false");
}
else
mailnewsEnableMapi.setAttribute("disabled", "true");
}
function onEnableMapi() {
// save the state of the checkbox
if ("mapiPref" in parent)
parent.mapiPref.isDefaultMailClient =
document.getElementById("mailnewsEnableMapi").checked;
}
function onOK()
{
try {
var mapiRegistry = Components.classes[ "@mozilla.org/mapiregistry;1" ].
getService( Components.interfaces.nsIMapiRegistry );
}
catch(ex){
mapiRegistry = null;
}
if (mapiRegistry &&
("mapiPref" in parent) &&
(mapiRegistry.isDefaultMailClient != parent.mapiPref.isDefaultMailClient)) {
if (parent.mapiPref.isDefaultMailClient)
mapiRegistry.setDefaultMailClient();
else
mapiRegistry.unsetDefaultMailClient();
}
}

View File

@@ -0,0 +1,44 @@
<?xml version="1.0"?>
<!--
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/
oftware 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 Netscape are
Copyright (C) 2001 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Srilatha Moturi <srilatha@netscape.com>
-->
<!DOCTYPE window [
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
%brandDTD;
<!ENTITY % prefMailnewsOverlayDTD SYSTEM "chrome://messenger-mapi/locale/pref-mailnewsOverlay.dtd" >
%prefMailnewsOverlayDTD;
]>
<overlay id="prefMailnewsOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript">
<![CDATA[
_elementIDs.push("mailnewsEnableMapi");
]]>
</script>
<script type="application/x-javascript" src="chrome://messenger-mapi/content/pref-mailnewsOverlay.js"/>
<hbox autostretch="never" id="mapi">
<checkbox id="mailnewsEnableMapi" label="&enableMapi.label;"
accesskey="&enableMapi.accesskey;"
preftype="bool" prefstring="mailnews.default_mail_client" prefattribute="checked"/>
</hbox>
</overlay>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the skins being supplied by this package -->
<RDF:Seq about="urn:mozilla:locale:root">
<RDF:li resource="urn:mozilla:locale:en-US"/>
</RDF:Seq>
<!-- locale information -->
<RDF:Description about="urn:mozilla:locale:en-US">
<chrome:packages>
<RDF:Seq about="urn:mozilla:locale:en-US:packages">
<RDF:li resource="urn:mozilla:locale:en-US:messenger-mapi"/>
</RDF:Seq>
</chrome:packages>
</RDF:Description>
<!-- Version Information. State that we work only with major version of this
package. -->
<RDF:Description about="urn:mozilla:locale:en-US:messenger-mapi"
chrome:localeVersion="0.9.7"/>
</RDF:RDF>

View File

@@ -0,0 +1,4 @@
en-US.jar:
locale/en-US/messenger-mapi/pref-mailnewsOverlay.dtd
locale/en-US/messenger-mapi/mapi.properties
locale/en-US/messenger-mapi/contents.rdf

View File

@@ -0,0 +1,40 @@
#!nmake
#
# 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 Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
DEPTH=..\..\..\..\..
CHROME_DIR=locales\en-US
CHROME_L10N_DIR=messenger\locale
CHROME_L10N = \
.\pref-mailnewsOverlay.dtd \
.\mapi.properties \
.\contents.rdf \
$(NULL)
include <$(DEPTH)\config\rules.mak>
chrome::
$(REGCHROME) locale en-US/messenger-mapi en-US.jar

View File

@@ -0,0 +1,23 @@
# Mail Integration Dialog
dialogTitle=%S Mail
dialogText=Do you want to use %S as the default mail application?
checkboxText=Do not display this dialog again
# MAPI Messages
loginText=Please enter your password for %S:
loginTextwithName=Please enter your username and password
loginTitle=%S Mail
PasswordTitle=%S Mail
# MAPI Error Messages
errorMessage=%S Mail could not be set as the default mail application because a registry key could not be updated. Verify with your system administrator that you have write access to your system registry, and then try again.
errorMessageTitle=%S Mail
# MAPI Security Messages
mapiBlindSendWarning=Another application is attempting to send mail using your user profile. Are you sure you want to send mail?
mapiBlindSendDontShowAgain=Warn me whenever other applications try to send mail from me
#Default Mail Display String
# localization note, $1%S is the app name, $2%S is the version
defaultMailDisplayTitle=%S %S Mail

View File

@@ -0,0 +1,3 @@
<!ENTITY enableMapiTitle.label "When sending mail from other applications">
<!ENTITY enableMapi.label "Use &vendorShortName; Mail as the default mail application.">
<!ENTITY enableMapi.accesskey "u">

View File

@@ -0,0 +1,28 @@
#!nmake
#
# 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 Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
DEPTH=..\..\..\..
DIRS=en-US
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,27 @@
#
# 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 Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
DEPTH=..\..\..
DIRS=content locale
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,602 +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
# des.c wants _X86_ defined for intel CPUs.
# coreconf does this for windows, but not for Linux, FreeBSD, etc.
ifeq ($(CPU_ARCH),x86)
ifneq (,$(filter-out WIN%,$(OS_TARGET)))
OS_REL_CFLAGS += -D_X86_
endif
endif
ifeq ($(OS_TARGET),OSF1)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
MPI_SRCS += mpvalpha.c
endif
ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) #omits WIN16 and 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
# 64-bit Windows
# 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
# DEFINES += -DMP_USE_UINT_DIGIT
# -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
ASFILES += mpcpucache_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
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
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
ARCHFLAG = -Aa +e +DA2.0 +DS2.0
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)
# The -R '$ORIGIN' linker option instructs this library to search for its
# dependencies in the same directory where it resides.
MKSHLIB += -R '$$ORIGIN'
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 =
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
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
MPI_SRCS += mpi_amd64.c
else
# Solaris x86
DEFINES += -D_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 mac_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

View File

@@ -1,413 +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.4 2005-08-06 07:24:21 nelsonb%netscape.com Exp $ */
/* $Id: aeskeywrap.c,v 1.4 2005-08-06 07:24:21 nelsonb%netscape.com Exp $ */
#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

View File

@@ -1,515 +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.7 2005-08-06 07:24:21 nelsonb%netscape.com Exp $ */
#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 (_X86_)
#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;
}

View File

@@ -1,193 +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 ***** */
#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;
}

View File

@@ -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

View File

@@ -1,117 +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.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
#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;
}

View File

@@ -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

View File

@@ -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):
;
; 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

View File

@@ -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

View File

@@ -1,640 +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. */
#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 longs, not bytes, on CPUs that take
* much longer to write bytes than to write longs, 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) && !defined(__sparc))
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;
}
#endif
#ifndef 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

View File

@@ -1,380 +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.20 2007-02-28 19:47:37 rrelyea%redhat.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
#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 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 ;
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;
/***************************************************************************
** RSA Public and Private Key structures
*/
/* member names from PKCS#1, section 7.1 */
struct RSAPublicKeyStr {
PRArenaPool * arena;
SECItem modulus;
SECItem publicExponent;
};
typedef struct RSAPublicKeyStr RSAPublicKey;
/* member names from PKCS#1, section 7.2 */
struct RSAPrivateKeyStr {
PRArenaPool * 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 {
PRArenaPool *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 {
PRArenaPool * 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 {
PRArenaPool * arena;
SECItem prime; /* p */
SECItem base; /* g */
};
typedef struct DHParamsStr DHParams;
struct DHPublicKeyStr {
PRArenaPool * arena;
SECItem prime;
SECItem base;
SECItem publicValue;
};
typedef struct DHPublicKeyStr DHPublicKey;
struct DHPrivateKeyStr {
PRArenaPool * 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 {
PRArenaPool * 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

View File

@@ -1,119 +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
# 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
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-lnssutil3 \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
else # ! NS_USE_GCC
EXTRA_SHARED_LIBS += \
$(DIST)/lib/nssutil3.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
$(NULL)
endif # NS_USE_GCC
else
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-lnssutil3 \
-L$(NSPR_LIB_DIR) \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
endif
endif

View File

@@ -1,689 +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);
#define BYTESWAP(word, temp) \
word = (word >> 16) | (word << 16); \
temp = 0x00ff00ff; \
word = ((word & temp) << 8) | ((word >> 8) & temp);
#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(_X86_)
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(_X86_)
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(_X86_)
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.
*/

View File

@@ -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

View File

@@ -1,301 +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 ***** */
#include "des.h"
#include <stddef.h>
#include "secerr.h"
#if defined(_X86_)
/* 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;
}

View File

@@ -1,388 +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.7 2004-04-25 15:03:08 gerv%gerv.net Exp $
*/
#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, &params->prime) );
SECITEM_TO_MPINT(key->prime, &p);
/* Set private key's g */
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, &params->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;
unsigned int len = 0, 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);
/* 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;
}

View File

@@ -1,450 +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.18 2005-10-12 00:48:25 wtchang%redhat.com Exp $ */
#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
/* DSA-specific random number function defined in prng_fips1861.c. */
extern SECStatus
DSA_GenerateGlobalRandomBytes(void *dest, size_t len, const unsigned char *q);
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,
&params->prime) );
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
&params->subPrime) );
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, &params->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

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -1,652 +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_
#ifndef NSS_ECC_MORE_THAN_SUITE_B
#error This source file is for Extended ECC only .
#endif
/* NIST prime curves */
static const ECCurveParams ecCurve_NIST_P192 = {
"NIST-P192", ECField_GFp, 192,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 1
};
static const ECCurveParams ecCurve_NIST_P224 = {
"NIST-P224", ECField_GFp, 224,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 1
};
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
};
/* NIST binary curves */
static const ECCurveParams ecCurve_NIST_K163 = {
"NIST-K163", ECField_GF2m, 163,
"0800000000000000000000000000000000000000C9",
"000000000000000000000000000000000000000001",
"000000000000000000000000000000000000000001",
"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
"04000000000000000000020108A2E0CC0D99F8A5EF", 2
};
static const ECCurveParams ecCurve_NIST_B163 = {
"NIST-B163", ECField_GF2m, 163,
"0800000000000000000000000000000000000000C9",
"000000000000000000000000000000000000000001",
"020A601907B8C953CA1481EB10512F78744A3205FD",
"03F0EBA16286A2D57EA0991168D4994637E8343E36",
"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
"040000000000000000000292FE77E70C12A4234C33", 2
};
static const ECCurveParams ecCurve_NIST_K233 = {
"NIST-K233", ECField_GF2m, 233,
"020000000000000000000000000000000000000004000000000000000001",
"000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000001",
"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4
};
static const ECCurveParams ecCurve_NIST_B233 = {
"NIST-B233", ECField_GF2m, 233,
"020000000000000000000000000000000000000004000000000000000001",
"000000000000000000000000000000000000000000000000000000000001",
"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 2
};
static const ECCurveParams ecCurve_NIST_K283 = {
"NIST-K283", ECField_GF2m, 283,
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
"000000000000000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000000000000000001",
"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
4
};
static const ECCurveParams ecCurve_NIST_B283 = {
"NIST-B283", ECField_GF2m, 283,
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
"000000000000000000000000000000000000000000000000000000000000000000000001",
"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
2
};
static const ECCurveParams ecCurve_NIST_K409 = {
"NIST-K409", ECField_GF2m, 409,
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
4
};
static const ECCurveParams ecCurve_NIST_B409 = {
"NIST-B409", ECField_GF2m, 409,
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
2
};
static const ECCurveParams ecCurve_NIST_K571 = {
"NIST-K571", ECField_GF2m, 571,
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
4
};
static const ECCurveParams ecCurve_NIST_B571 = {
"NIST-B571", ECField_GF2m, 571,
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
2
};
/* ANSI X9.62 prime curves */
static const ECCurveParams ecCurve_X9_62_PRIME_192V2 = {
"X9.62 P-192V2", ECField_GFp, 192,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
"CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
"EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
"6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
"FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 1
};
static const ECCurveParams ecCurve_X9_62_PRIME_192V3 = {
"X9.62 P-192V3", ECField_GFp, 192,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
"22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
"7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
"38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
"FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", 1
};
static const ECCurveParams ecCurve_X9_62_PRIME_239V1 = {
"X9.62 P-239V1", ECField_GFp, 239,
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
"6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
"0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
"7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", 1
};
static const ECCurveParams ecCurve_X9_62_PRIME_239V2 = {
"X9.62 P-239V2", ECField_GFp, 239,
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
"617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
"38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
"5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
"7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", 1
};
static const ECCurveParams ecCurve_X9_62_PRIME_239V3 = {
"X9.62 P-239V3", ECField_GFp, 239,
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
"255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
"6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
"1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", 1
};
/* ANSI X9.62 binary curves */
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V1 = {
"X9.62 C2-PNB163V1", ECField_GF2m, 163,
"080000000000000000000000000000000000000107",
"072546B5435234A422E0789675F432C89435DE5242",
"00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9",
"07AF69989546103D79329FCC3D74880F33BBE803CB",
"01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F",
"0400000000000000000001E60FC8821CC74DAEAFC1", 2
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V2 = {
"X9.62 C2-PNB163V2", ECField_GF2m, 163,
"080000000000000000000000000000000000000107",
"0108B39E77C4B108BED981ED0E890E117C511CF072",
"0667ACEB38AF4E488C407433FFAE4F1C811638DF20",
"0024266E4EB5106D0A964D92C4860E2671DB9B6CC5",
"079F684DDF6684C5CD258B3890021B2386DFD19FC5",
"03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 2
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V3 = {
"X9.62 C2-PNB163V3", ECField_GF2m, 163,
"080000000000000000000000000000000000000107",
"07A526C63D3E25A256A007699F5447E32AE456B50E",
"03F7061798EB99E238FD6F1BF95B48FEEB4854252B",
"02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB",
"05B935590C155E17EA48EB3FF3718B893DF59A05D0",
"03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 2
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB176V1 = {
"X9.62 C2-PNB176V1", ECField_GF2m, 176,
"0100000000000000000000000000000000080000000007",
"E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B",
"5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2",
"8D16C2866798B600F9F08BB4A8E860F3298CE04A5798",
"6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C",
"00010092537397ECA4F6145799D62B0A19CE06FE26AD", 0xFF6E
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V1 = {
"X9.62 C2-TNB191V1", ECField_GF2m, 191,
"800000000000000000000000000000000000000000000201",
"2866537B676752636A68F56554E12640276B649EF7526267",
"2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC",
"36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D",
"765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB",
"40000000000000000000000004A20E90C39067C893BBB9A5", 2
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V2 = {
"X9.62 C2-TNB191V2", ECField_GF2m, 191,
"800000000000000000000000000000000000000000000201",
"401028774D7777C7B7666D1366EA432071274F89FF01E718",
"0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01",
"3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10",
"17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A",
"20000000000000000000000050508CB89F652824E06B8173", 4
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V3 = {
"X9.62 C2-TNB191V3", ECField_GF2m, 191,
"800000000000000000000000000000000000000000000201",
"6C01074756099122221056911C77D77E77A777E7E7E77FCB",
"71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8",
"375D4CE24FDE434489DE8746E71786015009E66E38A926DD",
"545A39176196575D985999366E6AD34CE0A77CD7127B06BE",
"155555555555555555555555610C0B196812BFB6288A3EA3", 6
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB208W1 = {
"X9.62 C2-PNB208W1", ECField_GF2m, 208,
"010000000000000000000000000000000800000000000000000007",
"0000000000000000000000000000000000000000000000000000",
"C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E",
"89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A",
"0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3",
"000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 0xFE48
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V1 = {
"X9.62 C2-TNB239V1", ECField_GF2m, 239,
"800000000000000000000000000000000000000000000000001000000001",
"32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
"790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
"57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D",
"61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305",
"2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 4
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V2 = {
"X9.62 C2-TNB239V2", ECField_GF2m, 239,
"800000000000000000000000000000000000000000000000001000000001",
"4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F",
"5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B",
"28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205",
"5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833",
"1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 6
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V3 = {
"X9.62 C2-TNB239V3", ECField_GF2m, 239,
"800000000000000000000000000000000000000000000000001000000001",
"01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F",
"6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40",
"70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92",
"2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461",
"0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 0xA
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB272W1 = {
"X9.62 C2-PNB272W1", ECField_GF2m, 272,
"010000000000000000000000000000000000000000000000000000010000000000000B",
"91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20",
"7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7",
"6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D",
"10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23",
"000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521",
0xFF06
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB304W1 = {
"X9.62 C2-PNB304W1", ECField_GF2m, 304,
"010000000000000000000000000000000000000000000000000000000000000000000000000807",
"FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681",
"BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE",
"197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614",
"E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B",
"000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D",
0xFE2E
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB359V1 = {
"X9.62 C2-TNB359V1", ECField_GF2m, 359,
"800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001",
"5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557",
"2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988",
"3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097",
"53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD",
"01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B",
0x4C
};
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB368W1 = {
"X9.62 C2-PNB368W1", ECField_GF2m, 368,
"0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007",
"E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D",
"FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A",
"1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F",
"7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310",
"00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967",
0xFF70
};
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB431R1 = {
"X9.62 C2-TNB431R1", ECField_GF2m, 431,
"800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001",
"1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F",
"10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618",
"120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7",
"20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760",
"0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91",
0x2760
};
/* SEC2 prime curves */
static const ECCurveParams ecCurve_SECG_PRIME_112R1 = {
"SECP-112R1", ECField_GFp, 112,
"DB7C2ABF62E35E668076BEAD208B",
"DB7C2ABF62E35E668076BEAD2088",
"659EF8BA043916EEDE8911702B22",
"09487239995A5EE76B55F9C2F098",
"A89CE5AF8724C0A23E0E0FF77500",
"DB7C2ABF62E35E7628DFAC6561C5", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_112R2 = {
"SECP-112R2", ECField_GFp, 112,
"DB7C2ABF62E35E668076BEAD208B",
"6127C24C05F38A0AAAF65C0EF02C",
"51DEF1815DB5ED74FCC34C85D709",
"4BA30AB5E892B4E1649DD0928643",
"adcd46f5882e3747def36e956e97",
"36DF0AAFD8B8D7597CA10520D04B", 4
};
static const ECCurveParams ecCurve_SECG_PRIME_128R1 = {
"SECP-128R1", ECField_GFp, 128,
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
"E87579C11079F43DD824993C2CEE5ED3",
"161FF7528B899B2D0C28607CA52C5B86",
"CF5AC8395BAFEB13C02DA292DDED7A83",
"FFFFFFFE0000000075A30D1B9038A115", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_128R2 = {
"SECP-128R2", ECField_GFp, 128,
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
"D6031998D1B3BBFEBF59CC9BBFF9AEE1",
"5EEEFCA380D02919DC2C6558BB6D8A5D",
"7B6AA5D85E572983E6FB32A7CDEBC140",
"27B6916A894D3AEE7106FE805FC34B44",
"3FFFFFFF7FFFFFFFBE0024720613B5A3", 4
};
static const ECCurveParams ecCurve_SECG_PRIME_160K1 = {
"SECP-160K1", ECField_GFp, 160,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
"0000000000000000000000000000000000000000",
"0000000000000000000000000000000000000007",
"3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
"938CF935318FDCED6BC28286531733C3F03C4FEE",
"0100000000000000000001B8FA16DFAB9ACA16B6B3", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_160R1 = {
"SECP-160R1", ECField_GFp, 160,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
"4A96B5688EF573284664698968C38BB913CBFC82",
"23A628553168947D59DCC912042351377AC5FB32",
"0100000000000000000001F4C8F927AED3CA752257", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_160R2 = {
"SECP-160R2", ECField_GFp, 160,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
"B4E134D3FB59EB8BAB57274904664D5AF50388BA",
"52DCB034293A117E1F4FF11B30F7199D3144CE6D",
"FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
"0100000000000000000000351EE786A818F3A1A16B", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_192K1 = {
"SECP-192K1", ECField_GFp, 192,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
"000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000003",
"DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
"9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_224K1 = {
"SECP-224K1", ECField_GFp, 224,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
"00000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000000000000000000000000005",
"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 1
};
static const ECCurveParams ecCurve_SECG_PRIME_256K1 = {
"SECP-256K1", ECField_GFp, 256,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000007",
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 1
};
/* SEC2 binary curves */
static const ECCurveParams ecCurve_SECG_CHAR2_113R1 = {
"SECT-113R1", ECField_GF2m, 113,
"020000000000000000000000000201",
"003088250CA6E7C7FE649CE85820F7",
"00E8BEE4D3E2260744188BE0E9C723",
"009D73616F35F4AB1407D73562C10F",
"00A52830277958EE84D1315ED31886",
"0100000000000000D9CCEC8A39E56F", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_113R2 = {
"SECT-113R2", ECField_GF2m, 113,
"020000000000000000000000000201",
"00689918DBEC7E5A0DD6DFC0AA55C7",
"0095E9A9EC9B297BD4BF36E059184F",
"01A57A6A7B26CA5EF52FCDB8164797",
"00B3ADC94ED1FE674C06E695BABA1D",
"010000000000000108789B2496AF93", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_131R1 = {
"SECT-131R1", ECField_GF2m, 131,
"080000000000000000000000000000010D",
"07A11B09A76B562144418FF3FF8C2570B8",
"0217C05610884B63B9C6C7291678F9D341",
"0081BAF91FDF9833C40F9C181343638399",
"078C6E7EA38C001F73C8134B1B4EF9E150",
"0400000000000000023123953A9464B54D", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_131R2 = {
"SECT-131R2", ECField_GF2m, 131,
"080000000000000000000000000000010D",
"03E5A88919D7CAFCBF415F07C2176573B2",
"04B8266A46C55657AC734CE38F018F2192",
"0356DCD8F2F95031AD652D23951BB366A8",
"0648F06D867940A5366D9E265DE9EB240F",
"0400000000000000016954A233049BA98F", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_163R1 = {
"SECT-163R1", ECField_GF2m, 163,
"0800000000000000000000000000000000000000C9",
"07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
"0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
"0369979697AB43897789566789567F787A7876A654",
"00435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
"03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_193R1 = {
"SECT-193R1", ECField_GF2m, 193,
"02000000000000000000000000000000000000000000008001",
"0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
"00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
"01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1",
"0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
"01000000000000000000000000C7F34A778F443ACC920EBA49", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_193R2 = {
"SECT-193R2", ECField_GF2m, 193,
"02000000000000000000000000000000000000000000008001",
"0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
"00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
"00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F",
"01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
"010000000000000000000000015AAB561B005413CCD4EE99D5", 2
};
static const ECCurveParams ecCurve_SECG_CHAR2_239K1 = {
"SECT-239K1", ECField_GF2m, 239,
"800000000000000000004000000000000000000000000000000000000001",
"000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000001",
"29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC",
"76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
"2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", 4
};
/* WTLS curves */
static const ECCurveParams ecCurve_WTLS_1 = {
"WTLS-1", ECField_GF2m, 113,
"020000000000000000000000000201",
"000000000000000000000000000001",
"000000000000000000000000000001",
"01667979A40BA497E5D5C270780617",
"00F44B4AF1ECC2630E08785CEBCC15",
"00FFFFFFFFFFFFFFFDBF91AF6DEA73", 2
};
static const ECCurveParams ecCurve_WTLS_8 = {
"WTLS-8", ECField_GFp, 112,
"FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
"0000000000000000000000000000",
"0000000000000000000000000003",
"0000000000000000000000000001",
"0000000000000000000000000002",
"0100000000000001ECEA551AD837E9", 1
};
static const ECCurveParams ecCurve_WTLS_9 = {
"WTLS-9", ECField_GFp, 160,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
"0000000000000000000000000000000000000000",
"0000000000000000000000000000000000000003",
"0000000000000000000000000000000000000001",
"0000000000000000000000000000000000000002",
"0100000000000000000001CDC98AE0E2DE574ABF33", 1
};
/* mapping between ECCurveName enum and pointers to ECCurveParams */
static const ECCurveParams *ecCurve_map[] = {
NULL, /* ECCurve_noName */
&ecCurve_NIST_P192, /* ECCurve_NIST_P192 */
&ecCurve_NIST_P224, /* ECCurve_NIST_P224 */
&ecCurve_NIST_P256, /* ECCurve_NIST_P256 */
&ecCurve_NIST_P384, /* ECCurve_NIST_P384 */
&ecCurve_NIST_P521, /* ECCurve_NIST_P521 */
&ecCurve_NIST_K163, /* ECCurve_NIST_K163 */
&ecCurve_NIST_B163, /* ECCurve_NIST_B163 */
&ecCurve_NIST_K233, /* ECCurve_NIST_K233 */
&ecCurve_NIST_B233, /* ECCurve_NIST_B233 */
&ecCurve_NIST_K283, /* ECCurve_NIST_K283 */
&ecCurve_NIST_B283, /* ECCurve_NIST_B283 */
&ecCurve_NIST_K409, /* ECCurve_NIST_K409 */
&ecCurve_NIST_B409, /* ECCurve_NIST_B409 */
&ecCurve_NIST_K571, /* ECCurve_NIST_K571 */
&ecCurve_NIST_B571, /* ECCurve_NIST_B571 */
&ecCurve_X9_62_PRIME_192V2, /* ECCurve_X9_62_PRIME_192V2 */
&ecCurve_X9_62_PRIME_192V3, /* ECCurve_X9_62_PRIME_192V3 */
&ecCurve_X9_62_PRIME_239V1, /* ECCurve_X9_62_PRIME_239V1 */
&ecCurve_X9_62_PRIME_239V2, /* ECCurve_X9_62_PRIME_239V2 */
&ecCurve_X9_62_PRIME_239V3, /* ECCurve_X9_62_PRIME_239V3 */
&ecCurve_X9_62_CHAR2_PNB163V1, /* ECCurve_X9_62_CHAR2_PNB163V1 */
&ecCurve_X9_62_CHAR2_PNB163V2, /* ECCurve_X9_62_CHAR2_PNB163V2 */
&ecCurve_X9_62_CHAR2_PNB163V3, /* ECCurve_X9_62_CHAR2_PNB163V3 */
&ecCurve_X9_62_CHAR2_PNB176V1, /* ECCurve_X9_62_CHAR2_PNB176V1 */
&ecCurve_X9_62_CHAR2_TNB191V1, /* ECCurve_X9_62_CHAR2_TNB191V1 */
&ecCurve_X9_62_CHAR2_TNB191V2, /* ECCurve_X9_62_CHAR2_TNB191V2 */
&ecCurve_X9_62_CHAR2_TNB191V3, /* ECCurve_X9_62_CHAR2_TNB191V3 */
&ecCurve_X9_62_CHAR2_PNB208W1, /* ECCurve_X9_62_CHAR2_PNB208W1 */
&ecCurve_X9_62_CHAR2_TNB239V1, /* ECCurve_X9_62_CHAR2_TNB239V1 */
&ecCurve_X9_62_CHAR2_TNB239V2, /* ECCurve_X9_62_CHAR2_TNB239V2 */
&ecCurve_X9_62_CHAR2_TNB239V3, /* ECCurve_X9_62_CHAR2_TNB239V3 */
&ecCurve_X9_62_CHAR2_PNB272W1, /* ECCurve_X9_62_CHAR2_PNB272W1 */
&ecCurve_X9_62_CHAR2_PNB304W1, /* ECCurve_X9_62_CHAR2_PNB304W1 */
&ecCurve_X9_62_CHAR2_TNB359V1, /* ECCurve_X9_62_CHAR2_TNB359V1 */
&ecCurve_X9_62_CHAR2_PNB368W1, /* ECCurve_X9_62_CHAR2_PNB368W1 */
&ecCurve_X9_62_CHAR2_TNB431R1, /* ECCurve_X9_62_CHAR2_TNB431R1 */
&ecCurve_SECG_PRIME_112R1, /* ECCurve_SECG_PRIME_112R1 */
&ecCurve_SECG_PRIME_112R2, /* ECCurve_SECG_PRIME_112R2 */
&ecCurve_SECG_PRIME_128R1, /* ECCurve_SECG_PRIME_128R1 */
&ecCurve_SECG_PRIME_128R2, /* ECCurve_SECG_PRIME_128R2 */
&ecCurve_SECG_PRIME_160K1, /* ECCurve_SECG_PRIME_160K1 */
&ecCurve_SECG_PRIME_160R1, /* ECCurve_SECG_PRIME_160R1 */
&ecCurve_SECG_PRIME_160R2, /* ECCurve_SECG_PRIME_160R2 */
&ecCurve_SECG_PRIME_192K1, /* ECCurve_SECG_PRIME_192K1 */
&ecCurve_SECG_PRIME_224K1, /* ECCurve_SECG_PRIME_224K1 */
&ecCurve_SECG_PRIME_256K1, /* ECCurve_SECG_PRIME_256K1 */
&ecCurve_SECG_CHAR2_113R1, /* ECCurve_SECG_CHAR2_113R1 */
&ecCurve_SECG_CHAR2_113R2, /* ECCurve_SECG_CHAR2_113R2 */
&ecCurve_SECG_CHAR2_131R1, /* ECCurve_SECG_CHAR2_131R1 */
&ecCurve_SECG_CHAR2_131R2, /* ECCurve_SECG_CHAR2_131R2 */
&ecCurve_SECG_CHAR2_163R1, /* ECCurve_SECG_CHAR2_163R1 */
&ecCurve_SECG_CHAR2_193R1, /* ECCurve_SECG_CHAR2_193R1 */
&ecCurve_SECG_CHAR2_193R2, /* ECCurve_SECG_CHAR2_193R2 */
&ecCurve_SECG_CHAR2_239K1, /* ECCurve_SECG_CHAR2_239K1 */
&ecCurve_WTLS_1, /* ECCurve_WTLS_1 */
&ecCurve_WTLS_8, /* ECCurve_WTLS_8 */
&ecCurve_WTLS_9, /* ECCurve_WTLS_9 */
NULL /* ECCurve_pastLastCurve */
};
#endif

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -1,192 +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;
i = mpl_significant_bits(&meth->irr);
i += MP_DIGIT_BIT - 1;
mmm->b = i - i % MP_DIGIT_BIT;
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(mpl_lsh(a, r, mmm->b));
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;
}
}

View File

@@ -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 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 "mpi.h"
#include "mplogic.h"
#include "mpprime.h"
#include "mp_gf2m.h"
#include "ecl.h"
#include "ecl-curve.h"
#include "ec2.h"
#include <stdio.h>
#include <strings.h>
#include <assert.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
/* Time k repetitions of operation op. */
#define M_TimeOperation(op, k) { \
double dStart, dNow, dUserTime; \
struct rusage ru; \
int i; \
getrusage(RUSAGE_SELF, &ru); \
dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
for (i = 0; i < k; i++) { \
{ op; } \
}; \
getrusage(RUSAGE_SELF, &ru); \
dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
dUserTime = dNow-dStart; \
if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
}
/* Test curve using generic field arithmetic. */
#define ECTEST_GENERIC_GF2M(name_c, name) \
printf("Testing %s using generic implementation...\n", name_c); \
params = EC_GetNamedCurveParams(name); \
if (params == NULL) { \
printf(" Error: could not construct params.\n"); \
res = MP_NO; \
goto CLEANUP; \
} \
ECGroup_free(group); \
group = ECGroup_fromHex(params); \
if (group == NULL) { \
printf(" Error: could not construct group.\n"); \
res = MP_NO; \
goto CLEANUP; \
} \
MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 1) ); \
printf("... okay.\n");
/* Test curve using specific field arithmetic. */
#define ECTEST_NAMED_GF2M(name_c, name) \
printf("Testing %s using specific implementation...\n", name_c); \
ECGroup_free(group); \
group = ECGroup_fromName(name); \
if (group == NULL) { \
printf(" Warning: could not construct group.\n"); \
printf("... failed; continuing with remaining tests.\n"); \
} else { \
MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 0) ); \
printf("... okay.\n"); \
}
/* Performs basic tests of elliptic curve cryptography over binary
* polynomial fields. If tests fail, then it prints an error message,
* aborts, and returns an error code. Otherwise, returns 0. */
int
ectest_curve_GF2m(ECGroup *group, int ectestPrint, int ectestTime,
int generic)
{
mp_int one, order_1, gx, gy, rx, ry, n;
int size;
mp_err res;
char s[1000];
/* initialize values */
MP_CHECKOK(mp_init(&one));
MP_CHECKOK(mp_init(&order_1));
MP_CHECKOK(mp_init(&gx));
MP_CHECKOK(mp_init(&gy));
MP_CHECKOK(mp_init(&rx));
MP_CHECKOK(mp_init(&ry));
MP_CHECKOK(mp_init(&n));
MP_CHECKOK(mp_set_int(&one, 1));
MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
/* encode base point */
if (group->meth->field_dec) {
MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
} else {
MP_CHECKOK(mp_copy(&group->genx, &gx));
MP_CHECKOK(mp_copy(&group->geny, &gy));
}
if (ectestPrint) {
/* output base point */
printf(" base point P:\n");
MP_CHECKOK(mp_toradix(&gx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&gy, s, 16));
printf(" %s\n", s);
if (group->meth->field_enc) {
printf(" base point P (encoded):\n");
MP_CHECKOK(mp_toradix(&group->genx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&group->geny, s, 16));
printf(" %s\n", s);
}
}
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ec_GF2m_pt_mul_aff
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
if (ectestPrint) {
printf(" (order-1)*P (affine):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
if ((mp_cmp(&rx, &group->genx) != 0)
|| (mp_cmp(&ry, &group->geny) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ec_GF2m_pt_mul_mont
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
if (ectestPrint) {
printf(" (order-1)*P (montgomery):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
if ((mp_cmp(&rx, &group->genx) != 0)
|| (mp_cmp(&ry, &group->geny) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#ifdef ECL_ENABLE_GF2M_PROJ
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ec_GF2m_pt_mul_proj
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
if (ectestPrint) {
printf(" (order-1)*P (projective):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
if ((mp_cmp(&rx, &group->genx) != 0)
|| (mp_cmp(&ry, &group->geny) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
if (ectestPrint) {
printf(" (order-1)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
if (ectestPrint) {
printf(" (order-1)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ec_GF2m_pt_mul_aff
(&group->order, &group->genx, &group->geny, &rx, &ry,
group));
if (ectestPrint) {
printf(" (order)*P (affine):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ec_GF2m_pt_mul_mont
(&group->order, &group->genx, &group->geny, &rx, &ry,
group));
if (ectestPrint) {
printf(" (order)*P (montgomery):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
#ifdef ECL_ENABLE_GF2M_PROJ
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ec_GF2m_pt_mul_proj
(&group->order, &group->genx, &group->geny, &rx, &ry,
group));
if (ectestPrint) {
printf(" (order)*P (projective):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
if (ectestPrint) {
printf(" (order)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
if (ectestPrint) {
printf(" (order)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
/* check that (order-1)P + (order-1)P + P == (order-1)P */
MP_CHECKOK(ECPoints_mul
(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
if (ectestPrint) {
printf
(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
/* test validate_point function */
if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
printf(" Error: validate point on base point failed.\n");
res = MP_NO;
goto CLEANUP;
}
MP_CHECKOK(mp_add_d(&gy, 1, &ry));
if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
printf(" Error: validate point on invalid point passed.\n");
res = MP_NO;
goto CLEANUP;
}
if (ectestTime) {
/* compute random scalar */
size = mpl_significant_bits(&group->meth->irr);
if (size < MP_OKAY) {
goto CLEANUP;
}
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
/* timed test */
if (generic) {
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
M_TimeOperation(MP_CHECKOK
(ec_GF2m_pt_mul_aff
(&n, &group->genx, &group->geny, &rx, &ry,
group)), 100);
#endif
M_TimeOperation(MP_CHECKOK
(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
100);
M_TimeOperation(MP_CHECKOK
(ECPoints_mul
(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
} else {
M_TimeOperation(MP_CHECKOK
(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
100);
M_TimeOperation(MP_CHECKOK
(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
100);
M_TimeOperation(MP_CHECKOK
(ECPoints_mul
(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
}
}
CLEANUP:
mp_clear(&one);
mp_clear(&order_1);
mp_clear(&gx);
mp_clear(&gy);
mp_clear(&rx);
mp_clear(&ry);
mp_clear(&n);
if (res != MP_OKAY) {
printf(" Error: exiting with error value %i\n", res);
}
return res;
}
/* Prints help information. */
void
printUsage()
{
printf("Usage: ecp_test [--print] [--time]\n");
printf
(" --print Print out results of each point arithmetic test.\n");
printf
(" --time Benchmark point operations and print results.\n");
}
/* Performs tests of elliptic curve cryptography over binary polynomial
* fields. If tests fail, then it prints an error message, aborts, and
* returns an error code. Otherwise, returns 0. */
int
main(int argv, char **argc)
{
int ectestTime = 0;
int ectestPrint = 0;
int i;
ECGroup *group = NULL;
ECCurveParams *params = NULL;
mp_err res;
/* read command-line arguments */
for (i = 1; i < argv; i++) {
if ((strcasecmp(argc[i], "time") == 0)
|| (strcasecmp(argc[i], "-time") == 0)
|| (strcasecmp(argc[i], "--time") == 0)) {
ectestTime = 1;
} else if ((strcasecmp(argc[i], "print") == 0)
|| (strcasecmp(argc[i], "-print") == 0)
|| (strcasecmp(argc[i], "--print") == 0)) {
ectestPrint = 1;
} else {
printUsage();
return 0;
}
}
/* generic arithmetic tests */
ECTEST_GENERIC_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1);
/* specific arithmetic tests */
ECTEST_NAMED_GF2M("NIST-K163", ECCurve_NIST_K163);
ECTEST_NAMED_GF2M("NIST-B163", ECCurve_NIST_B163);
ECTEST_NAMED_GF2M("NIST-K233", ECCurve_NIST_K233);
ECTEST_NAMED_GF2M("NIST-B233", ECCurve_NIST_B233);
ECTEST_NAMED_GF2M("NIST-K283", ECCurve_NIST_K283);
ECTEST_NAMED_GF2M("NIST-B283", ECCurve_NIST_B283);
ECTEST_NAMED_GF2M("NIST-K409", ECCurve_NIST_K409);
ECTEST_NAMED_GF2M("NIST-B409", ECCurve_NIST_B409);
ECTEST_NAMED_GF2M("NIST-K571", ECCurve_NIST_K571);
ECTEST_NAMED_GF2M("NIST-B571", ECCurve_NIST_B571);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V1", ECCurve_X9_62_CHAR2_PNB163V1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V2", ECCurve_X9_62_CHAR2_PNB163V2);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V3", ECCurve_X9_62_CHAR2_PNB163V3);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB176V1", ECCurve_X9_62_CHAR2_PNB176V1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V1", ECCurve_X9_62_CHAR2_TNB191V1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V2", ECCurve_X9_62_CHAR2_TNB191V2);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V3", ECCurve_X9_62_CHAR2_TNB191V3);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB208W1", ECCurve_X9_62_CHAR2_PNB208W1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V1", ECCurve_X9_62_CHAR2_TNB239V1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V2", ECCurve_X9_62_CHAR2_TNB239V2);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V3", ECCurve_X9_62_CHAR2_TNB239V3);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB272W1", ECCurve_X9_62_CHAR2_PNB272W1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB304W1", ECCurve_X9_62_CHAR2_PNB304W1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB359V1", ECCurve_X9_62_CHAR2_TNB359V1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB368W1", ECCurve_X9_62_CHAR2_PNB368W1);
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB431R1", ECCurve_X9_62_CHAR2_TNB431R1);
ECTEST_NAMED_GF2M("SECT-113R1", ECCurve_SECG_CHAR2_113R1);
ECTEST_NAMED_GF2M("SECT-113R2", ECCurve_SECG_CHAR2_113R2);
ECTEST_NAMED_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1);
ECTEST_NAMED_GF2M("SECT-131R2", ECCurve_SECG_CHAR2_131R2);
ECTEST_NAMED_GF2M("SECT-163K1", ECCurve_SECG_CHAR2_163K1);
ECTEST_NAMED_GF2M("SECT-163R1", ECCurve_SECG_CHAR2_163R1);
ECTEST_NAMED_GF2M("SECT-163R2", ECCurve_SECG_CHAR2_163R2);
ECTEST_NAMED_GF2M("SECT-193R1", ECCurve_SECG_CHAR2_193R1);
ECTEST_NAMED_GF2M("SECT-193R2", ECCurve_SECG_CHAR2_193R2);
ECTEST_NAMED_GF2M("SECT-233K1", ECCurve_SECG_CHAR2_233K1);
ECTEST_NAMED_GF2M("SECT-233R1", ECCurve_SECG_CHAR2_233R1);
ECTEST_NAMED_GF2M("SECT-239K1", ECCurve_SECG_CHAR2_239K1);
ECTEST_NAMED_GF2M("SECT-283K1", ECCurve_SECG_CHAR2_283K1);
ECTEST_NAMED_GF2M("SECT-283R1", ECCurve_SECG_CHAR2_283R1);
ECTEST_NAMED_GF2M("SECT-409K1", ECCurve_SECG_CHAR2_409K1);
ECTEST_NAMED_GF2M("SECT-409R1", ECCurve_SECG_CHAR2_409R1);
ECTEST_NAMED_GF2M("SECT-571K1", ECCurve_SECG_CHAR2_571K1);
ECTEST_NAMED_GF2M("SECT-571R1", ECCurve_SECG_CHAR2_571R1);
ECTEST_NAMED_GF2M("WTLS-1 (113)", ECCurve_WTLS_1);
ECTEST_NAMED_GF2M("WTLS-3 (163)", ECCurve_WTLS_3);
ECTEST_NAMED_GF2M("WTLS-4 (113)", ECCurve_WTLS_4);
ECTEST_NAMED_GF2M("WTLS-5 (163)", ECCurve_WTLS_5);
ECTEST_NAMED_GF2M("WTLS-10 (233)", ECCurve_WTLS_10);
ECTEST_NAMED_GF2M("WTLS-11 (233)", ECCurve_WTLS_11);
CLEANUP:
EC_FreeCurveParams(params);
ECGroup_free(group);
if (res != MP_OKAY) {
printf("Error: exiting with error value %i\n", res);
}
return res;
}

View File

@@ -1,151 +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 "mpi.h"
#include "mplogic.h"
#include "ecl.h"
#include "ecp.h"
#include "ecl-priv.h"
#include <sys/types.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
/* Returns 2^e as an integer. This is meant to be used for small powers of
* two. */
int ec_twoTo(int e);
/* Number of bits of scalar to test */
#define BITSIZE 160
/* Time k repetitions of operation op. */
#define M_TimeOperation(op, k) { \
double dStart, dNow, dUserTime; \
struct rusage ru; \
int i; \
getrusage(RUSAGE_SELF, &ru); \
dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
for (i = 0; i < k; i++) { \
{ op; } \
}; \
getrusage(RUSAGE_SELF, &ru); \
dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
dUserTime = dNow-dStart; \
if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
}
/* Tests wNAF computation. Non-adjacent-form 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
main(void)
{
signed char naf[BITSIZE + 1];
ECGroup *group = NULL;
mp_int k;
mp_int *scalar;
int i, count;
int res;
int w = 5;
char s[1000];
/* Get a 160 bit scalar to compute wNAF from */
group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1);
scalar = &group->genx;
/* Compute wNAF representation of scalar */
ec_compute_wNAF(naf, BITSIZE, scalar, w);
/* Verify correctness of representation */
mp_init(&k); /* init k to 0 */
for (i = BITSIZE; i >= 0; i--) {
mp_add(&k, &k, &k);
/* digits in mp_???_d are unsigned */
if (naf[i] >= 0) {
mp_add_d(&k, naf[i], &k);
} else {
mp_sub_d(&k, -naf[i], &k);
}
}
if (mp_cmp(&k, scalar) != 0) {
printf("Error: incorrect NAF value.\n");
MP_CHECKOK(mp_toradix(&k, s, 16));
printf("NAF value %s\n", s);
MP_CHECKOK(mp_toradix(scalar, s, 16));
printf("original value %s\n", s);
goto CLEANUP;
}
/* Verify digits of representation are valid */
for (i = 0; i <= BITSIZE; i++) {
if (naf[i] % 2 == 0 && naf[i] != 0) {
printf("Error: Even non-zero digit found.\n");
goto CLEANUP;
}
if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) {
printf("Error: Magnitude of naf digit too large.\n");
goto CLEANUP;
}
}
/* Verify sparsity of representation */
count = w - 1;
for (i = 0; i <= BITSIZE; i++) {
if (naf[i] != 0) {
if (count < w - 1) {
printf("Error: Sparsity failed.\n");
goto CLEANUP;
}
count = 0;
} else
count++;
}
/* Check timing */
M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000);
printf("Test passed.\n");
CLEANUP:
ECGroup_free(group);
return MP_OKAY;
}

Some files were not shown because too many files have changed in this diff Show More