Compare commits
18 Commits
WIN64_MASM
...
MAPI_NEW_D
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e953a4ea87 | ||
|
|
22ea3cb16d | ||
|
|
e021985dac | ||
|
|
37c7fe2cc1 | ||
|
|
92449d5f2b | ||
|
|
0f4c47bad2 | ||
|
|
66a09211ae | ||
|
|
4d276aa864 | ||
|
|
9a9d38606a | ||
|
|
7ef7f62f45 | ||
|
|
412bc70111 | ||
|
|
cf982c25ce | ||
|
|
dfb5dde44f | ||
|
|
5b5ddf1efb | ||
|
|
2765860524 | ||
|
|
95560e128c | ||
|
|
2c4edc911e | ||
|
|
82d37c5f89 |
70
mozilla/mailnews/base/public/nsIMapiRegistry.idl
Normal file
70
mozilla/mailnews/base/public/nsIMapiRegistry.idl
Normal 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"
|
||||
%}
|
||||
27
mozilla/mailnews/mapi/makefile.win
Normal file
27
mozilla/mailnews/mapi/makefile.win
Normal 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>
|
||||
54
mozilla/mailnews/mapi/mapiDll/Mapi32.DEF
Normal file
54
mozilla/mailnews/mapi/mapiDll/Mapi32.DEF
Normal 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
|
||||
|
||||
346
mozilla/mailnews/mapi/mapiDll/MapiDll.cpp
Normal file
346
mozilla/mailnews/mapi/mapiDll/MapiDll.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
53
mozilla/security/nss/lib/freebl/mpi/utils/ptab.pl → mozilla/mailnews/mapi/mapiDll/makefile.win
Executable file → Normal file
53
mozilla/security/nss/lib/freebl/mpi/utils/ptab.pl → mozilla/mailnews/mapi/mapiDll/makefile.win
Executable file → Normal 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;
|
||||
@@ -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
|
||||
62
mozilla/security/nss/lib/freebl/mpi/doc/build → mozilla/mailnews/mapi/mapihook/build/makefile.win
Executable file → Normal file
62
mozilla/security/nss/lib/freebl/mpi/doc/build → mozilla/mailnews/mapi/mapihook/build/makefile.win
Executable file → Normal 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."
|
||||
|
||||
114
mozilla/mailnews/mapi/mapihook/build/msgMapi.idl
Normal file
114
mozilla/mailnews/mapi/mapihook/build/msgMapi.idl
Normal 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();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
70
mozilla/mailnews/mapi/mapihook/public/nsIMapiRegistry.idl
Normal file
70
mozilla/mailnews/mapi/mapihook/public/nsIMapiRegistry.idl
Normal 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"
|
||||
%}
|
||||
@@ -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"
|
||||
%}
|
||||
|
||||
|
||||
323
mozilla/mailnews/mapi/mapihook/src/Registry.cpp
Normal file
323
mozilla/mailnews/mapi/mapihook/src/Registry.cpp
Normal 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;
|
||||
}
|
||||
@@ -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
|
||||
107
mozilla/mailnews/mapi/mapihook/src/makefile.win
Normal file
107
mozilla/mailnews/mapi/mapihook/src/makefile.win
Normal 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>
|
||||
118
mozilla/mailnews/mapi/mapihook/src/msgMapiFactory.cpp
Normal file
118
mozilla/mailnews/mapi/mapihook/src/msgMapiFactory.cpp
Normal 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 ;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
777
mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp
Normal file
777
mozilla/mailnews/mapi/mapihook/src/msgMapiHook.cpp
Normal 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 ;
|
||||
}
|
||||
@@ -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_
|
||||
266
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.cpp
Normal file
266
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
92
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.h
Normal file
92
mozilla/mailnews/mapi/mapihook/src/msgMapiImp.h
Normal 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
|
||||
376
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.cpp
Normal file
376
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.cpp
Normal 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;
|
||||
}
|
||||
|
||||
112
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.h
Normal file
112
mozilla/mailnews/mapi/mapihook/src/msgMapiMain.h
Normal 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_
|
||||
209
mozilla/mailnews/mapi/mapihook/src/msgMapiSupport.cpp
Normal file
209
mozilla/mailnews/mapi/mapihook/src/msgMapiSupport.cpp
Normal 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);
|
||||
|
||||
@@ -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_
|
||||
167
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistry.cpp
Normal file
167
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistry.cpp
Normal 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;
|
||||
}
|
||||
|
||||
76
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistry.h
Normal file
76
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistry.h
Normal 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____
|
||||
743
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.cpp
Normal file
743
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.cpp
Normal 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;
|
||||
}
|
||||
|
||||
112
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.h
Normal file
112
mozilla/mailnews/mapi/mapihook/src/nsMapiRegistryUtils.h
Normal 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
|
||||
30
mozilla/mailnews/mapi/resources/content/contents.rdf
Normal file
30
mozilla/mailnews/mapi/resources/content/contents.rdf
Normal 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>
|
||||
3
mozilla/mailnews/mapi/resources/content/jar.mn
Normal file
3
mozilla/mailnews/mapi/resources/content/jar.mn
Normal file
@@ -0,0 +1,3 @@
|
||||
messenger.jar:
|
||||
content/messenger-mapi/pref-mailnewsOverlay.xul
|
||||
content/messenger-mapi/contents.rdf
|
||||
29
mozilla/mailnews/mapi/resources/content/makefile.win
Normal file
29
mozilla/mailnews/mapi/resources/content/makefile.win
Normal 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
|
||||
14
mozilla/mailnews/mapi/resources/content/overlays.rdf
Normal file
14
mozilla/mailnews/mapi/resources/content/overlays.rdf
Normal 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>
|
||||
104
mozilla/mailnews/mapi/resources/content/pref-mailnewsOverlay.js
Normal file
104
mozilla/mailnews/mapi/resources/content/pref-mailnewsOverlay.js
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
23
mozilla/mailnews/mapi/resources/locale/en-US/contents.rdf
Normal file
23
mozilla/mailnews/mapi/resources/locale/en-US/contents.rdf
Normal 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>
|
||||
4
mozilla/mailnews/mapi/resources/locale/en-US/jar.mn
Normal file
4
mozilla/mailnews/mapi/resources/locale/en-US/jar.mn
Normal 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
|
||||
40
mozilla/mailnews/mapi/resources/locale/en-US/makefile.win
Normal file
40
mozilla/mailnews/mapi/resources/locale/en-US/makefile.win
Normal 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
|
||||
|
||||
23
mozilla/mailnews/mapi/resources/locale/en-US/mapi.properties
Normal file
23
mozilla/mailnews/mapi/resources/locale/en-US/mapi.properties
Normal 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
|
||||
|
||||
@@ -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">
|
||||
28
mozilla/mailnews/mapi/resources/locale/makefile.win
Normal file
28
mozilla/mailnews/mapi/resources/locale/makefile.win
Normal 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>
|
||||
27
mozilla/mailnews/mapi/resources/makefile.win
Normal file
27
mozilla/mailnews/mapi/resources/makefile.win
Normal 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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _ALGHMAC_H_
|
||||
#define _ALGHMAC_H_
|
||||
|
||||
typedef struct HMACContextStr HMACContext;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/* destroy HMAC context */
|
||||
extern void
|
||||
HMAC_Destroy(HMACContext *cx, PRBool freeit);
|
||||
|
||||
/* create HMAC context
|
||||
* hash_obj hash object from SECRawHashObjects[]
|
||||
* secret the secret with which the HMAC is performed.
|
||||
* secret_len the length of the secret.
|
||||
* isFIPS true if conforming to FIPS 198.
|
||||
*
|
||||
* NULL is returned if an error occurs.
|
||||
*/
|
||||
extern HMACContext *
|
||||
HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS);
|
||||
|
||||
/* like HMAC_Create, except caller allocates HMACContext. */
|
||||
SECStatus
|
||||
HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj,
|
||||
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS);
|
||||
|
||||
/* reset HMAC for a fresh round */
|
||||
extern void
|
||||
HMAC_Begin(HMACContext *cx);
|
||||
|
||||
/* update HMAC
|
||||
* cx HMAC Context
|
||||
* data the data to perform HMAC on
|
||||
* data_len the length of the data to process
|
||||
*/
|
||||
extern void
|
||||
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len);
|
||||
|
||||
/* Finish HMAC -- place the results within result
|
||||
* cx HMAC context
|
||||
* result buffer for resulting hmac'd data
|
||||
* result_len where the resultant hmac length is stored
|
||||
* max_result_len maximum possible length that can be stored in result
|
||||
*/
|
||||
extern SECStatus
|
||||
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
|
||||
unsigned int max_result_len);
|
||||
|
||||
/* clone a copy of the HMAC state. this is usefult when you would
|
||||
* need to keep a running hmac but also need to extract portions
|
||||
* partway through the process.
|
||||
*/
|
||||
extern HMACContext *
|
||||
HMAC_Clone(HMACContext *cx);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
@@ -1,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;
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Marc Bevand <bevand_m@epita.fr> .
|
||||
# Portions created by the Initial Developer are
|
||||
# Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# ** ARCFOUR implementation optimized for AMD64.
|
||||
# **
|
||||
# ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
# ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.globl ARCFOUR
|
||||
.type ARCFOUR,@function
|
||||
ARCFOUR:
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
movq %rdi, %rbp # key = ARG(key)
|
||||
movq %rsi, %rbx # rbx = ARG(len)
|
||||
movq %rdx, %rsi # in = ARG(in)
|
||||
movq %rcx, %rdi # out = ARG(out)
|
||||
movq (%rbp), %rcx # x = key->x
|
||||
movq 8(%rbp), %rdx # y = key->y
|
||||
addq $16, %rbp # d = key->data
|
||||
incq %rcx # x++
|
||||
andq $255, %rcx # x &= 0xff
|
||||
leaq -8(%rbx,%rsi), %rbx # rbx = in+len-8
|
||||
movq %rbx, %r9 # tmp = in+len-8
|
||||
movq 0(%rbp,%rcx,8), %rax # tx = d[x]
|
||||
cmpq %rsi, %rbx # cmp in with in+len-8
|
||||
jl .Lend # jump if (in+len-8 < in)
|
||||
|
||||
.Lstart:
|
||||
addq $8, %rsi # increment in
|
||||
addq $8, %rdi # increment out
|
||||
|
||||
# generate the next 8 bytes of the rc4 stream into %r8
|
||||
movq $8, %r11 # byte counter
|
||||
1: addb %al, %dl # y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx # ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) # d[x] = ty
|
||||
addb %al, %bl # val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) # d[y] = tx
|
||||
incb %cl # x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax # tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b # val = d[val]
|
||||
decb %r11b
|
||||
rorq $8, %r8 # (ror does not change ZF)
|
||||
jnz 1b
|
||||
|
||||
# xor 8 bytes
|
||||
xorq -8(%rsi), %r8
|
||||
cmpq %r9, %rsi # cmp in+len-8 with in
|
||||
movq %r8, -8(%rdi)
|
||||
jle .Lstart # jump if (in <= in+len-8)
|
||||
|
||||
.Lend:
|
||||
addq $8, %r9 # tmp = in+len
|
||||
|
||||
# handle the last bytes, one by one
|
||||
1: cmpq %rsi, %r9 # cmp in with in+len
|
||||
jle .Lfinished # jump if (in+len <= in)
|
||||
addb %al, %dl # y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx # ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) # d[x] = ty
|
||||
addb %al, %bl # val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) # d[y] = tx
|
||||
incb %cl # x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax # tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b # val = d[val]
|
||||
xorb (%rsi), %r8b # xor 1 byte
|
||||
movb %r8b, (%rdi)
|
||||
incq %rsi # in++
|
||||
incq %rdi # out++
|
||||
jmp 1b
|
||||
|
||||
.Lfinished:
|
||||
decq %rcx # x--
|
||||
movb %dl, -8(%rbp) # key->y = y
|
||||
movb %cl, -16(%rbp) # key->x = x
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
ret
|
||||
.L_ARCFOUR_end:
|
||||
.size ARCFOUR,.L_ARCFOUR_end-ARCFOUR
|
||||
|
||||
# Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
.previous
|
||||
@@ -1,139 +0,0 @@
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; Marc Bevand <bevand_m@epita.fr> .
|
||||
; Portions created by the Initial Developer are
|
||||
; Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
; ** ARCFOUR implementation optimized for AMD64.
|
||||
; **
|
||||
; ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
; ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.CODE
|
||||
|
||||
; extern void ARCFOUR(RC4Context *cx, unsigned long long inputLen,
|
||||
; const unsigned char *input, unsigned char *output);
|
||||
|
||||
|
||||
ARCFOUR PROC
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push rsi
|
||||
push rdi
|
||||
|
||||
mov rbp, rcx ; key = ARG(key)
|
||||
mov rbx, rdx ; rbx = ARG(len)
|
||||
mov rsi, r8 ; in = ARG(in)
|
||||
mov rdi, r9 ; out = ARG(out)
|
||||
mov rcx, [rbp] ; x = key->x
|
||||
mov rdx, [rbp+8] ; y = key->y
|
||||
add rbp, 16 ; d = key->data
|
||||
inc rcx ; x++
|
||||
and rcx, 0ffh ; x &= 0xff
|
||||
lea rbx, [rbx+rsi-8] ; rbx = in+len-8
|
||||
mov r9, rbx ; tmp = in+len-8
|
||||
mov rax, [rbp+rcx*8] ; tx = d[x]
|
||||
cmp rbx, rsi ; cmp in with in+len-8
|
||||
jl Lend ; jump if (in+len-8 < in)
|
||||
|
||||
Lstart:
|
||||
add rsi, 8 ; increment in
|
||||
add rdi, 8 ; increment out
|
||||
|
||||
;
|
||||
; generate the next 8 bytes of the rc4 stream into r8
|
||||
;
|
||||
|
||||
mov r11, 8 ; byte counter
|
||||
|
||||
@@:
|
||||
add dl, al ; y += tx
|
||||
mov ebx, [rbp+rdx*8] ; ty = d[y]
|
||||
mov [rbp+rcx*8], ebx ; d[x] = ty
|
||||
add bl, al ; val = ty + tx
|
||||
mov [rbp+rdx*8], eax ; d[y] = tx
|
||||
inc cl ; x++ (NEXT ROUND)
|
||||
mov eax, [rbp+rcx*8] ; tx = d[x] (NEXT ROUND)
|
||||
mov r8b, [rbp+rbx*8] ; val = d[val]
|
||||
dec r11b
|
||||
ror r8, 8 ; (ror does not change ZF)
|
||||
jnz @b
|
||||
|
||||
;
|
||||
; xor 8 bytes
|
||||
;
|
||||
|
||||
xor r8, [rsi-8]
|
||||
cmp rsi, r9 ; cmp in+len-8 with in
|
||||
mov [rdi-8], r8
|
||||
jle Lstart
|
||||
|
||||
Lend:
|
||||
add r9, 8 ; tmp = in+len
|
||||
|
||||
;
|
||||
; handle the last bytes, one by one
|
||||
;
|
||||
|
||||
@@:
|
||||
cmp r9, rsi ; cmp in with in+len
|
||||
jle Lfinished ; jump if (in+len <= in)
|
||||
add dl, al ; y += tx
|
||||
mov ebx, [rbp+rdx*8] ; ty = d[y]
|
||||
mov [rbp+rcx*8], ebx ; d[x] = ty
|
||||
add bl, al ; val = ty + tx
|
||||
mov [rbp+rdx*8], eax ; d[y] = tx
|
||||
inc cl ; x++ (NEXT ROUND)
|
||||
mov eax, [rbp+rcx*8] ; tx = d[x] (NEXT ROUND)
|
||||
mov r8b, [rbp+rbx*8] ; val = d[val]
|
||||
xor r8b, [rsi] ; xor 1 byte
|
||||
mov [rdi], r8b
|
||||
inc rsi ; in++
|
||||
inc rdi
|
||||
jmp @b
|
||||
|
||||
Lfinished:
|
||||
dec rcx ; x--
|
||||
mov [rbp-8], dl ; key->y = y
|
||||
mov [rbp-16], cl ; key->x = x
|
||||
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
ARCFOUR ENDP
|
||||
|
||||
END
|
||||
@@ -1,116 +0,0 @@
|
||||
/ ***** BEGIN LICENSE BLOCK *****
|
||||
/ Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public License Version
|
||||
/ 1.1 (the "License"); you may not use this file except in compliance with
|
||||
/ the License. You may obtain a copy of the License at
|
||||
/ http://www.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS IS" basis,
|
||||
/ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
/ for the specific language governing rights and limitations under the
|
||||
/ License.
|
||||
/
|
||||
/ The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
/
|
||||
/ The Initial Developer of the Original Code is
|
||||
/ Marc Bevand <bevand_m@epita.fr> .
|
||||
/ Portions created by the Initial Developer are
|
||||
/ Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the terms of
|
||||
/ either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
/ the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
/ in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
/ of those above. If you wish to allow use of your version of this file only
|
||||
/ under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
/ use your version of this file under the terms of the MPL, indicate your
|
||||
/ decision by deleting the provisions above and replace them with the notice
|
||||
/ and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
/ the provisions above, a recipient may use your version of this file under
|
||||
/ the terms of any one of the MPL, the GPL or the LGPL.
|
||||
/
|
||||
/ ***** END LICENSE BLOCK *****
|
||||
|
||||
/ ** ARCFOUR implementation optimized for AMD64.
|
||||
/ **
|
||||
/ ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
/ ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.globl ARCFOUR
|
||||
.type ARCFOUR,@function
|
||||
ARCFOUR:
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
movq %rdi, %rbp / key = ARG(key)
|
||||
movq %rsi, %rbx / rbx = ARG(len)
|
||||
movq %rdx, %rsi / in = ARG(in)
|
||||
movq %rcx, %rdi / out = ARG(out)
|
||||
movq (%rbp), %rcx / x = key->x
|
||||
movq 8(%rbp), %rdx / y = key->y
|
||||
addq $16, %rbp / d = key->data
|
||||
incq %rcx / x++
|
||||
andq $255, %rcx / x &= 0xff
|
||||
leaq -8(%rbx,%rsi), %rbx / rbx = in+len-8
|
||||
movq %rbx, %r9 / tmp = in+len-8
|
||||
movq 0(%rbp,%rcx,8), %rax / tx = d[x]
|
||||
cmpq %rsi, %rbx / cmp in with in+len-8
|
||||
jl .Lend / jump if (in+len-8 < in)
|
||||
|
||||
.Lstart:
|
||||
addq $8, %rsi / increment in
|
||||
addq $8, %rdi / increment out
|
||||
|
||||
/ generate the next 8 bytes of the rc4 stream into %r8
|
||||
movq $8, %r11 / byte counter
|
||||
1: addb %al, %dl / y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx / ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) / d[x] = ty
|
||||
addb %al, %bl / val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) / d[y] = tx
|
||||
incb %cl / x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax / tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b / val = d[val]
|
||||
decb %r11b
|
||||
rorq $8, %r8 / (ror does not change ZF)
|
||||
jnz 1b
|
||||
|
||||
/ xor 8 bytes
|
||||
xorq -8(%rsi), %r8
|
||||
cmpq %r9, %rsi / cmp in+len-8 with in
|
||||
movq %r8, -8(%rdi)
|
||||
jle .Lstart / jump if (in <= in+len-8)
|
||||
|
||||
.Lend:
|
||||
addq $8, %r9 / tmp = in+len
|
||||
|
||||
/ handle the last bytes, one by one
|
||||
1: cmpq %rsi, %r9 / cmp in with in+len
|
||||
jle .Lfinished / jump if (in+len <= in)
|
||||
addb %al, %dl / y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx / ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) / d[x] = ty
|
||||
addb %al, %bl / val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) / d[y] = tx
|
||||
incb %cl / x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax / tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b / val = d[val]
|
||||
xorb (%rsi), %r8b / xor 1 byte
|
||||
movb %r8b, (%rdi)
|
||||
incq %rsi / in++
|
||||
incq %rdi / out++
|
||||
jmp 1b
|
||||
|
||||
.Lfinished:
|
||||
decq %rcx / x--
|
||||
movb %dl, -8(%rbp) / key->y = y
|
||||
movb %cl, -16(%rbp) / key->x = x
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
ret
|
||||
.L_ARCFOUR_end:
|
||||
.size ARCFOUR,.L_ARCFOUR_end-ARCFOUR
|
||||
@@ -1,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
@@ -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
@@ -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
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* des.h
|
||||
*
|
||||
* header file for DES-150 library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _DES_H_
|
||||
#define _DES_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned int HALF;
|
||||
|
||||
#define HALFPTR(x) ((HALF *)(x))
|
||||
#define SHORTPTR(x) ((unsigned short *)(x))
|
||||
#define BYTEPTR(x) ((BYTE *)(x))
|
||||
|
||||
typedef enum {
|
||||
DES_ENCRYPT = 0x5555,
|
||||
DES_DECRYPT = 0xAAAA
|
||||
} DESDirection;
|
||||
|
||||
typedef void DESFunc(struct DESContextStr *cx, BYTE *out, const BYTE *in,
|
||||
unsigned int len);
|
||||
|
||||
struct DESContextStr {
|
||||
/* key schedule, 16 internal keys, each with 8 6-bit parts */
|
||||
HALF ks0 [32];
|
||||
HALF ks1 [32];
|
||||
HALF ks2 [32];
|
||||
HALF iv [2];
|
||||
DESDirection direction;
|
||||
DESFunc *worker;
|
||||
};
|
||||
|
||||
void DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction);
|
||||
void DES_Do1Block( HALF * ks, const BYTE * inbuf, BYTE * outbuf);
|
||||
|
||||
#endif
|
||||
@@ -1,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;
|
||||
}
|
||||
@@ -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, ¶ms->prime) );
|
||||
SECITEM_TO_MPINT(key->prime, &p);
|
||||
/* Set private key's g */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) );
|
||||
SECITEM_TO_MPINT(key->base, &g);
|
||||
/* Generate private key xa */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DH_SECRET_KEY_LEN);
|
||||
RNG_GenerateGlobalRandomBytes(key->privateValue.data,
|
||||
key->privateValue.len);
|
||||
SECITEM_TO_MPINT( key->privateValue, &xa );
|
||||
/* xa < p */
|
||||
CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
|
||||
/* Compute public key Ya = g ** xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
|
||||
MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
|
||||
*privKey = key;
|
||||
cleanup:
|
||||
mp_clear(&g);
|
||||
mp_clear(&xa);
|
||||
mp_clear(&p);
|
||||
mp_clear(&Ya);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem *publicValue,
|
||||
SECItem *prime,
|
||||
SECItem *privateValue,
|
||||
SECItem *derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
mp_int p, Xa, Yb, ZZ;
|
||||
mp_err err = MP_OKAY;
|
||||
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;
|
||||
}
|
||||
@@ -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,
|
||||
¶ms->prime) );
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
|
||||
¶ms->subPrime) );
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) );
|
||||
/* Convert stored p, g, and received x into MPI integers. */
|
||||
SECITEM_TO_MPINT(params->prime, &p);
|
||||
SECITEM_TO_MPINT(params->base, &g);
|
||||
OCTETS_TO_MPINT(xb, &x, DSA_SUBPRIME_LEN);
|
||||
/* Store x in private key */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
|
||||
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
|
||||
/* Compute public key y = g**x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
|
||||
/* Store y in public key */
|
||||
MPINT_TO_SECITEM(&y, &key->publicValue, arena);
|
||||
*privKey = key;
|
||||
key = NULL;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&y);
|
||||
if (key)
|
||||
PORT_FreeArena(key->params.arena, PR_TRUE);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
** "params" is a pointer to the PQG parameters for the domain
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned char seed[DSA_SUBPRIME_LEN];
|
||||
int retries = 10;
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
do {
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
|
||||
params->subPrime.data))
|
||||
return SECFailure;
|
||||
/* Disallow values of 0 and 1 for x. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN-1; i++) {
|
||||
if (seed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good && seed[i] > 1) {
|
||||
good = PR_TRUE;
|
||||
}
|
||||
} while (!good && --retries > 0);
|
||||
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Generate a new DSA key using random seed. */
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
|
||||
SECStatus
|
||||
DSA_NewKeyFromSeed(const PQGParams *params,
|
||||
const unsigned char *seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
|
||||
const unsigned char *kb)
|
||||
{
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int x, k; /* private key & pseudo-random integer */
|
||||
mp_int r, s; /* tuple (r, s) is signature) */
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len < DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&s) );
|
||||
/*
|
||||
** Convert stored PQG and private key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->privateValue, &x);
|
||||
OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN);
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 1
|
||||
**
|
||||
** r = (g**k mod p) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
|
||||
CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 2
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + x*r)) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
|
||||
CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
|
||||
CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
|
||||
CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
|
||||
/*
|
||||
** verify r != 0 and s != 0
|
||||
** mentioned as optional in FIPS 186-1.
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
** Step 4
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = MP_OKAY;
|
||||
signature->len = DSA_SIGNATURE_LEN;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 40 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
** On output, signature->len == size of signature in buffer.
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv;
|
||||
int retries = 10;
|
||||
unsigned char kSeed[DSA_SUBPRIME_LEN];
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
PORT_SetError(0);
|
||||
do {
|
||||
rv = DSA_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
|
||||
key->params.subPrime.data);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
/* Disallow a value of 0 for k. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN; i++) {
|
||||
if (kSeed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
continue;
|
||||
}
|
||||
rv = dsa_SignDigest(key, signature, digest, kSeed);
|
||||
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
|
||||
--retries > 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes. */
|
||||
SECStatus
|
||||
DSA_SignDigestWithSeed(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_SignDigest(key, signature, digest, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int u1, u2, v, w; /* intermediate values used in verification */
|
||||
mp_int y; /* public key */
|
||||
mp_err err;
|
||||
SECStatus verified = SECFailure;
|
||||
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r_) );
|
||||
CHECK_MPI_OK( mp_init(&s_) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&v) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
/*
|
||||
** Convert stored PQG and public key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->publicValue, &y);
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
|
||||
OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
|
||||
/*
|
||||
** Verify that 0 < r' < q and 0 < s' < q
|
||||
*/
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
|
||||
/* err is zero here. */
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
goto cleanup; /* will return verified == SECFailure */
|
||||
}
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 1
|
||||
**
|
||||
** w = (s')**-1 mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 2
|
||||
**
|
||||
** u1 = ((SHA1(M')) * w) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 3
|
||||
**
|
||||
** u2 = ((r') * w) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 4
|
||||
**
|
||||
** v = ((g**u1 * y**u2) mod p) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
|
||||
CHECK_MPI_OK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
|
||||
CHECK_MPI_OK( mp_mod(&v, &q, &v) ); /* v = v mod q */
|
||||
/*
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
verified = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
verified = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&w);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
}
|
||||
return verified;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ec_h_
|
||||
#define __ec_h_
|
||||
|
||||
#define EC_DEBUG 0
|
||||
#define EC_POINT_FORM_COMPRESSED_Y0 0x02
|
||||
#define EC_POINT_FORM_COMPRESSED_Y1 0x03
|
||||
#define EC_POINT_FORM_UNCOMPRESSED 0x04
|
||||
#define EC_POINT_FORM_HYBRID_Y0 0x06
|
||||
#define EC_POINT_FORM_HYBRID_Y1 0x07
|
||||
|
||||
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
|
||||
#define SECG_CURVE_OID_TOTAL_LEN 7
|
||||
|
||||
#endif /* __ec_h_ */
|
||||
@@ -1,230 +0,0 @@
|
||||
#
|
||||
# Makefile for elliptic curve library
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the elliptic curve math library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Sun Microsystems, Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2003
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Douglas Stebila <douglas@stebila.ca>
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
# Netscape Communications Corporation
|
||||
# Richard C. Swift (swift@netscape.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
#PERL=perl
|
||||
|
||||
include ../mpi/target.mk
|
||||
|
||||
##
|
||||
## Define platform-dependent variables for use of floating-point code.
|
||||
##
|
||||
ifeq ($(TARGET),v9SOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),v8plusSOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),v8SOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),x86LINUX)
|
||||
ECL_USE_FP=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
##
|
||||
## Add to definition of CFLAGS depending on use of floating-point code.
|
||||
##
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
CFLAGS+= -DECL_USE_FP
|
||||
endif
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=-L../mpi -lmpi -lm#-lmalloc#-lefence
|
||||
|
||||
##
|
||||
## Define INCLUDES to include any include directories you need to
|
||||
## compile with.
|
||||
##
|
||||
INCLUDES=-I../mpi
|
||||
CFLAGS+= $(INCLUDES) $(XCFLAGS)
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## Define LIBOBJS to be the object files that will be created during
|
||||
## the build process.
|
||||
##
|
||||
LIBOBJS = ecl.o ecl_curve.o ecl_mult.o ecl_gf.o \
|
||||
ec2_aff.o ec2_mont.o ec2_proj.o \
|
||||
ec2_163.o ec2_193.o ec2_233.o \
|
||||
ecp_aff.o ecp_jac.o ecp_mont.o \
|
||||
ec_naf.o ecp_jm.o \
|
||||
ecp_192.o ecp_224.o ecp_256.o ecp_384.o ecp_521.o
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
LIBOBJS+= ecp_fp160.o ecp_fp192.o ecp_fp224.o ecp_fp.o
|
||||
endif
|
||||
|
||||
## The headers contained in this library.
|
||||
LIBHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h
|
||||
APPHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h
|
||||
ifeq ($(ECL_GFP_ASSEMBLY_FP),1)
|
||||
LIBHDRS += ecp_fp.h
|
||||
APPHDRS += ecp_fp.h
|
||||
endif
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "libecl.a - elliptic curve library"
|
||||
@ echo "tests - build command line tests"
|
||||
@ echo "test - run command line tests"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .o .i
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
ecl.o: ecl.c $(LIBHDRS)
|
||||
ecl_curve.o: ecl_curve.c $(LIBHDRS)
|
||||
ecl_mult.o: ecl_mult.c $(LIBHDRS)
|
||||
ecl_gf.o: ecl_gf.c $(LIBHDRS)
|
||||
ec2_aff.o: ec2_aff.c $(LIBHDRS)
|
||||
ec2_mont.o: ec2_mont.c $(LIBHDRS)
|
||||
ec2_proj.o: ec2_proj.c $(LIBHDRS)
|
||||
ec2_163.o: ec2_163.c $(LIBHDRS)
|
||||
ec2_193.o: ec2_193.c $(LIBHDRS)
|
||||
ec2_233.o: ec2_233.c $(LIBHDRS)
|
||||
ecp_aff.o: ecp_aff.c $(LIBHDRS)
|
||||
ecp_jac.o: ecp_jac.c $(LIBHDRS)
|
||||
ecp_jm.o: ecp_jm.c $(LIBHDRS)
|
||||
ecp_mont.o: ecp_mont.c $(LIBHDRS)
|
||||
ecp_192.o: ecp_192.c $(LIBHDRS)
|
||||
ecp_224.o: ecp_224.c $(LIBHDRS)
|
||||
ecp_256.o: ecp_256.c $(LIBHDRS)
|
||||
ecp_384.o: ecp_384.c $(LIBHDRS)
|
||||
ecp_521.o: ecp_521.c $(LIBHDRS)
|
||||
ecp_fp.o: ecp_fp.c $(LIBHDRS)
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
ecp_fp160.o: ecp_fp160.c ecp_fpinc.c $(LIBHDRS)
|
||||
ecp_fp192.o: ecp_fp192.c ecp_fpinc.c $(LIBHDRS)
|
||||
ecp_fp224.o: ecp_fp224.c ecp_fpinc.c $(LIBHDRS)
|
||||
endif
|
||||
|
||||
libecl.a: $(LIBOBJS)
|
||||
ar -cvr libecl.a $(LIBOBJS)
|
||||
$(RANLIB) libecl.a
|
||||
|
||||
lib libs: libecl.a
|
||||
|
||||
ecl.i: ecl.h
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
ECLTESTOBJS = ec2_test.o ecp_test.o ec_naft.o
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
ECLTESTOBJS+= ecp_fpt.o
|
||||
endif
|
||||
ECLTESTS = $(ECLTESTOBJS:.o=)
|
||||
|
||||
$(ECLTESTOBJS): %.o: tests/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDES)
|
||||
|
||||
$(ECLTESTS): %: %.o libecl.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
tests: ec2_test ecp_test ec_naft ecp_fpt
|
||||
else
|
||||
tests: ec2_test ecp_test ec_naft
|
||||
endif
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
test: tests
|
||||
./ecp_test
|
||||
./ec2_test
|
||||
./ec_naft
|
||||
./ecp_fpt
|
||||
else
|
||||
test: tests
|
||||
./ecp_test
|
||||
./ec_naft
|
||||
./ec2_test
|
||||
endif
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.i
|
||||
rm -f core
|
||||
rm -f *~ .*~
|
||||
rm -f $(ECLTESTS)
|
||||
|
||||
clobber: clean
|
||||
|
||||
# END
|
||||
@@ -1,330 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the elliptic curve math library.
|
||||
|
||||
The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
Sun Microsystems, Inc. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Stephen Fung <fungstep@hotmail.com> and
|
||||
Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
The ECL exposes routines for constructing and converting curve
|
||||
parameters for internal use.
|
||||
|
||||
|
||||
HEADER FILES
|
||||
============
|
||||
|
||||
ecl-exp.h - Exports data structures and curve names. For use by code
|
||||
that does not have access to mp_ints.
|
||||
|
||||
ecl-curve.h - Provides hex encodings (in the form of ECCurveParams
|
||||
structs) of standardizes elliptic curve domain parameters and mappings
|
||||
from ECCurveName to ECCurveParams. For use by code that does not have
|
||||
access to mp_ints.
|
||||
|
||||
ecl.h - Interface to constructors for curve parameters and group object,
|
||||
and point multiplication operations. Used by higher level algorithms
|
||||
(like ECDH and ECDSA) to actually perform elliptic curve cryptography.
|
||||
|
||||
ecl-priv.h - Data structures and functions for internal use within the
|
||||
library.
|
||||
|
||||
ec2.h - Internal header file that contains all functions for point
|
||||
arithmetic over binary polynomial fields.
|
||||
|
||||
ecp.h - Internal header file that contains all functions for point
|
||||
arithmetic over prime fields.
|
||||
|
||||
DATA STRUCTURES AND TYPES
|
||||
=========================
|
||||
|
||||
ECCurveName (from ecl-exp.h) - Opaque name for standardized elliptic
|
||||
curve domain parameters.
|
||||
|
||||
ECCurveParams (from ecl-exp.h) - Provides hexadecimal encoding
|
||||
of elliptic curve domain parameters. Can be generated by a user
|
||||
and passed to ECGroup_fromHex or can be generated from a name by
|
||||
EC_GetNamedCurveParams. ecl-curve.h contains ECCurveParams structs for
|
||||
the standardized curves defined by ECCurveName.
|
||||
|
||||
ECGroup (from ecl.h and ecl-priv.h) - Opaque data structure that
|
||||
represents a group of elliptic curve points for a particular set of
|
||||
elliptic curve domain parameters. Contains all domain parameters (curve
|
||||
a and b, field, base point) as well as pointers to the functions that
|
||||
should be used for point arithmetic and the underlying field GFMethod.
|
||||
Generated by either ECGroup_fromHex or ECGroup_fromName.
|
||||
|
||||
GFMethod (from ecl-priv.h) - Represents a field underlying a set of
|
||||
elliptic curve domain parameters. Contains the irreducible that defines
|
||||
the field (either the prime or the binary polynomial) as well as
|
||||
pointers to the functions that should be used for field arithmetic.
|
||||
|
||||
ARITHMETIC FUNCTIONS
|
||||
====================
|
||||
|
||||
Higher-level algorithms (like ECDH and ECDSA) should call ECPoint_mul
|
||||
or ECPoints_mul (from ecl.h) to do point arithmetic. These functions
|
||||
will choose which underlying algorithms to use, based on the ECGroup
|
||||
structure.
|
||||
|
||||
Point Multiplication
|
||||
--------------------
|
||||
|
||||
ecl_mult.c provides the ECPoints_mul and ECPoint_mul wrappers.
|
||||
It also provides two implementations for the pts_mul operation -
|
||||
ec_pts_mul_basic (which computes kP, lQ, and then adds kP + lQ) and
|
||||
ec_pts_mul_simul_w2 (which does a simultaneous point multiplication
|
||||
using a table with window size 2*2).
|
||||
|
||||
ec_naf.c provides an implementation of an algorithm to calculate a
|
||||
non-adjacent form of a scalar, minimizing the number of point
|
||||
additions that need to be done in a point multiplication.
|
||||
|
||||
Point Arithmetic over Prime Fields
|
||||
----------------------------------
|
||||
|
||||
ecp_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ecp_jac.c provides point arithmetic using Jacobian projective
|
||||
coordinates and mixed Jacobian-affine coordinates. (Jacobian projective
|
||||
coordinates represent a point (x, y) as (X, Y, Z), where x=X/Z^2,
|
||||
y=Y/Z^3).
|
||||
|
||||
ecp_jm.c provides point arithmetic using Modified Jacobian
|
||||
coordinates and mixed Modified_Jacobian-affine coordinates.
|
||||
(Modified Jacobian coordinates represent a point (x, y)
|
||||
as (X, Y, Z, a*Z^4), where x=X/Z^2, y=Y/Z^3, and a is
|
||||
the linear coefficient in the curve defining equation).
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized field arithmetic.
|
||||
|
||||
Point Arithmetic over Binary Polynomial Fields
|
||||
----------------------------------------------
|
||||
|
||||
ec2_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ec2_proj.c provides point arithmetic using projective coordinates.
|
||||
(Projective coordinates represent a point (x, y) as (X, Y, Z), where
|
||||
x=X/Z, y=Y/Z^2).
|
||||
|
||||
ec2_mont.c provides point multiplication using Montgomery projective
|
||||
coordinates.
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
|
||||
|
||||
Field Arithmetic
|
||||
----------------
|
||||
|
||||
ecl_gf.c provides constructors for field objects (GFMethod) with the
|
||||
functions GFMethod_cons*. It also provides wrappers around the basic
|
||||
field operations.
|
||||
|
||||
Prime Field Arithmetic
|
||||
----------------------
|
||||
|
||||
The mpi library provides the basic prime field arithmetic.
|
||||
|
||||
ecp_mont.c provides wrappers around the Montgomery multiplication
|
||||
functions from the mpi library and adds encoding and decoding functions.
|
||||
It also provides the function to construct a GFMethod object using
|
||||
Montgomery multiplication.
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized modular reduction for the
|
||||
fields defined by nistp192 and nistp224 primes.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Binary Polynomial Field Arithmetic
|
||||
----------------------------------
|
||||
|
||||
../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
|
||||
including addition, multiplication, squaring, mod, and division, as well
|
||||
as conversion ob polynomial representations between bitstring and int[].
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
|
||||
and sqr operations.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Field Encoding
|
||||
--------------
|
||||
|
||||
By default, field elements are encoded in their basic form. It is
|
||||
possible to use an alternative encoding, however. For example, it is
|
||||
possible to Montgomery representation of prime field elements and
|
||||
take advantage of the fast modular multiplication that Montgomery
|
||||
representation provides. The process of converting from basic form to
|
||||
Montgomery representation is called field encoding, and the opposite
|
||||
process would be field decoding. All internal point operations assume
|
||||
that the operands are field encoded as appropriate. By rewiring the
|
||||
underlying field arithmetic to perform operations on these encoded
|
||||
values, the same overlying point arithmetic operations can be used
|
||||
regardless of field representation.
|
||||
|
||||
ALGORITHM WIRING
|
||||
================
|
||||
|
||||
The EC library allows point and field arithmetic algorithms to be
|
||||
substituted ("wired-in") on a fine-grained basis. This allows for
|
||||
generic algorithms and algorithms that are optimized for a particular
|
||||
curve, field, or architecture, to coexist and to be automatically
|
||||
selected at runtime.
|
||||
|
||||
Wiring Mechanism
|
||||
----------------
|
||||
|
||||
The ECGroup and GFMethod structure contain pointers to the point and
|
||||
field arithmetic functions, respectively, that are to be used in
|
||||
operations.
|
||||
|
||||
The selection of algorithms to use is handled in the function
|
||||
ecgroup_fromNameAndHex in ecl.c.
|
||||
|
||||
Default Wiring
|
||||
--------------
|
||||
|
||||
Curves over prime fields by default use montgomery field arithmetic,
|
||||
point multiplication using 5-bit window non-adjacent-form with
|
||||
Modified Jacobian coordinates, and 2*2-bit simultaneous point
|
||||
multiplication using Jacobian coordinates.
|
||||
(Wiring in function ECGroup_consGFp_mont in ecl.c.)
|
||||
|
||||
Curves over prime fields that have optimized modular reduction (i.e.,
|
||||
secp160r1, nistp192, and nistp224) do not use Montgomery field
|
||||
arithmetic. Instead, they use basic field arithmetic with their
|
||||
optimized reduction (as in ecp_192.c and ecp_224.c). They
|
||||
use the same point multiplication and simultaneous point multiplication
|
||||
algorithms as other curves over prime fields.
|
||||
|
||||
Curves over binary polynomial fields by default use generic field
|
||||
arithmetic with montgomery point multiplication and basic kP + lQ
|
||||
computation (multiply, multiply, and add). (Wiring in function
|
||||
ECGroup_cons_GF2m in ecl.c.)
|
||||
|
||||
Curves over binary polynomial fields that have optimized field
|
||||
arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
|
||||
field arithmetic. They use the same point multiplication and
|
||||
simultaneous point multiplication algorithms as other curves over binary
|
||||
fields.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
We provide an example for plugging in an optimized implementation for
|
||||
the Koblitz curve nistk163.
|
||||
|
||||
Suppose the file ec2_k163.c contains the optimized implementation. In
|
||||
particular it contains a point multiplication function:
|
||||
|
||||
mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
Since only a pt_mul function is provided, the generic pt_add function
|
||||
will be used.
|
||||
|
||||
There are two options for handling the optimized field arithmetic used
|
||||
by the ..._pt_mul function. Say the optimized field arithmetic includes
|
||||
the following functions:
|
||||
|
||||
mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
|
||||
First, the optimized field arithmetic could simply be called directly
|
||||
by the ..._pt_mul function. This would be accomplished by changing
|
||||
the ecgroup_fromNameAndHex function in ecl.c to include the following
|
||||
statements:
|
||||
|
||||
if (name == ECCurve_NIST_K163) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
|
||||
&geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK( ec_group_set_nistk163(group) );
|
||||
}
|
||||
|
||||
and including in ec2_k163.c the following function:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
As a result, ec_GF2m_pt_add and similar functions would use the
|
||||
basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
|
||||
ec_GF2m_sqr, and ec_GF2m_div.
|
||||
|
||||
Alternatively, the optimized field arithmetic could be wired into the
|
||||
group's GFMethod. This would be accomplished by putting the following
|
||||
function in ec2_k163.c:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->meth->field_add = &ec_GF2m_nistk163_add;
|
||||
group->meth->field_mul = &ec_GF2m_nistk163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
|
||||
group->meth->field_div = &ec_GF2m_nistk163_div;
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
For an example of functions that use special field encodings, take a
|
||||
look at ecp_mont.c.
|
||||
|
||||
TESTING
|
||||
=======
|
||||
|
||||
The ecl/tests directory contains a collection of standalone tests that
|
||||
verify the correctness of the elliptic curve library.
|
||||
|
||||
Both ecp_test and ec2_test take the following arguments:
|
||||
|
||||
--print Print out results of each point arithmetic test.
|
||||
--time Benchmark point operations and print results.
|
||||
|
||||
The set of curves over which ecp_test and ec2_test run is coded into the
|
||||
program, but can be changed by editing the source files.
|
||||
|
||||
BUILDING
|
||||
========
|
||||
|
||||
The ecl can be built as a standalone library, separate from NSS,
|
||||
dependent only on the mpi library. To build the library:
|
||||
|
||||
> cd ../mpi
|
||||
> make libs
|
||||
> cd ../ecl
|
||||
> make libs
|
||||
> make tests # to build test files
|
||||
> make test # to run automated tests
|
||||
@@ -1,317 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the elliptic curve math library.
|
||||
|
||||
The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
Sun Microsystems, Inc. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Stephen Fung <fungstep@hotmail.com> and
|
||||
Nils Gura <nils.gura@sun.com>, Sun Microsystems Laboratories
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
The ECL exposes routines for constructing and converting curve
|
||||
parameters for internal use.
|
||||
|
||||
The floating point code of the ECL provides algorithms for performing
|
||||
elliptic-curve point multiplications in floating point.
|
||||
|
||||
The point multiplication algorithms perform calculations almost
|
||||
exclusively in floating point for efficiency, but have the same
|
||||
(integer) interface as the ECL for compatibility and to be easily
|
||||
wired-in to the ECL. Please see README file (not this README.FP file)
|
||||
for information on wiring-in.
|
||||
|
||||
This has been implemented for 3 curves as specified in [1]:
|
||||
secp160r1
|
||||
secp192r1
|
||||
secp224r1
|
||||
|
||||
RATIONALE
|
||||
=========
|
||||
Calculations are done in the floating-point unit (FPU) since it
|
||||
gives better performance on the UltraSPARC III chips. This is
|
||||
because the FPU allows for faster multiplication than the integer unit.
|
||||
The integer unit has a longer multiplication instruction latency, and
|
||||
does not allow full pipelining, as described in [2].
|
||||
Since performance is an important selling feature of Elliptic Curve
|
||||
Cryptography (ECC), this implementation was created.
|
||||
|
||||
DATA REPRESENTATION
|
||||
===================
|
||||
Data is primarily represented in an array of double-precision floating
|
||||
point numbers. Generally, each array element has 24 bits of precision
|
||||
(i.e. be x * 2^y, where x is an integer of at most 24 bits, y some positive
|
||||
integer), although the actual implementation details are more complicated.
|
||||
|
||||
e.g. a way to store an 80 bit number might be:
|
||||
double p[4] = { 632613 * 2^0, 329841 * 2^24, 9961 * 2^48, 51 * 2^64 };
|
||||
See section ARITHMETIC OPERATIONS for more details.
|
||||
|
||||
This implementation assumes that the floating-point unit rounding mode
|
||||
is round-to-even as specified in IEEE 754
|
||||
(as opposed to chopping, rounding up, or rounding down).
|
||||
When subtracting integers represented as arrays of floating point
|
||||
numbers, some coefficients (array elements) may become negative.
|
||||
This effectively gives an extra bit of precision that is important
|
||||
for correctness in some cases.
|
||||
|
||||
The described number presentation limits the size of integers to 1023 bits.
|
||||
This is due to an upper bound of 1024 for the exponent of a double precision
|
||||
floating point number as specified in IEEE-754.
|
||||
However, this is acceptable for ECC key sizes of the foreseeable future.
|
||||
|
||||
DATA STRUCTURES
|
||||
===============
|
||||
For more information on coordinate representations, see [3].
|
||||
|
||||
ecfp_aff_pt
|
||||
-----------
|
||||
Affine EC Point Representation. This is the basic
|
||||
representation (x, y) of an elliptic curve point.
|
||||
|
||||
ecfp_jac_pt
|
||||
-----------
|
||||
Jacobian EC Point. This stores a point as (X, Y, Z), where
|
||||
the affine point corresponds to (X/Z^2, Y/Z^3). This allows
|
||||
for fewer inversions in calculations.
|
||||
|
||||
ecfp_chud_pt
|
||||
------------
|
||||
Chudnovsky Jacobian Point. This representation stores a point
|
||||
as (X, Y, Z, Z^2, Z^3), the same as a Jacobian representation
|
||||
but also storing Z^2 and Z^3 for faster point additions.
|
||||
|
||||
ecfp_jm_pt
|
||||
----------
|
||||
Modified Jacobian Point. This representation stores a point
|
||||
as (X, Y, Z, a*Z^4), the same as Jacobian representation but
|
||||
also storing a*Z^4 for faster point doublings. Here "a" represents
|
||||
the linear coefficient of x defining the curve.
|
||||
|
||||
EC_group_fp
|
||||
-----------
|
||||
Stores information on the elliptic curve group for floating
|
||||
point calculations. Contains curve specific information, as
|
||||
well as function pointers to routines, allowing different
|
||||
optimizations to be easily wired in.
|
||||
This should be made accessible from an ECGroup for the floating
|
||||
point implementations of point multiplication.
|
||||
|
||||
POINT MULTIPLICATION ALGORITHMS
|
||||
===============================
|
||||
Elliptic Curve Point multiplication can be done at a higher level orthogonal
|
||||
to the implementation of point additions and point doublings. There
|
||||
are a variety of algorithms that can be used.
|
||||
|
||||
The following algorithms have been implemented:
|
||||
|
||||
4-bit Window (Jacobian Coordinates)
|
||||
Double & Add (Jacobian & Affine Coordinates)
|
||||
5-bit Non-Adjacent Form (Modified Jacobian & Chudnovsky Jacobian)
|
||||
|
||||
Currently, the fastest algorithm for multiplying a generic point
|
||||
is the 5-bit Non-Adjacent Form.
|
||||
|
||||
See comments in ecp_fp.c for more details and references.
|
||||
|
||||
SOURCE / HEADER FILES
|
||||
=====================
|
||||
|
||||
ecp_fp.c
|
||||
--------
|
||||
Main source file for floating point calculations. Contains routines
|
||||
to convert from floating-point to integer (mp_int format), point
|
||||
multiplication algorithms, and several other routines.
|
||||
|
||||
ecp_fp.h
|
||||
--------
|
||||
Main header file. Contains most constants used and function prototypes.
|
||||
|
||||
ecp_fp[160, 192, 224].c
|
||||
-----------------------
|
||||
Source files for specific curves. Contains curve specific code such
|
||||
as specialized reduction based on the field defining prime. Contains
|
||||
code wiring-in different algorithms and optimizations.
|
||||
|
||||
ecp_fpinc.c
|
||||
-----------
|
||||
Source file that is included by ecp_fp[160, 192, 224].c. This generates
|
||||
functions with different preprocessor-defined names and loop iterations,
|
||||
allowing for static linking and strong compiler optimizations without
|
||||
code duplication.
|
||||
|
||||
TESTING
|
||||
=======
|
||||
The test suite can be found in ecl/tests/ecp_fpt. This tests and gets
|
||||
timings of the different algorithms for the curves implemented.
|
||||
|
||||
ARITHMETIC OPERATIONS
|
||||
---------------------
|
||||
The primary operations in ECC over the prime fields are modular arithmetic:
|
||||
i.e. n * m (mod p) and n + m (mod p). In this implementation, multiplication,
|
||||
addition, and reduction are implemented as separate functions. This
|
||||
enables computation of formulae with fewer reductions, e.g.
|
||||
(a * b) + (c * d) (mod p) rather than:
|
||||
((a * b) (mod p)) + ((c * d) (mod p)) (mod p)
|
||||
This takes advantage of the fact that the double precision mantissa in
|
||||
floating point can hold numbers up to 2^53, i.e. it has some leeway to
|
||||
store larger intermediate numbers. See further detail in the section on
|
||||
FLOATING POINT PRECISION.
|
||||
|
||||
Multiplication
|
||||
--------------
|
||||
Multiplication is implemented in a standard polynomial multiplication
|
||||
fashion. The terms in opposite factors are pairwise multiplied and
|
||||
added together appropriately. Note that the result requires twice
|
||||
as many doubles for storage, as the bit size of the product is twice
|
||||
that of the multiplicands.
|
||||
e.g. suppose we have double n[3], m[3], r[6], and want to calculate r = n * m
|
||||
r[0] = n[0] * m[0]
|
||||
r[1] = n[0] * m[1] + n[1] * m[0]
|
||||
r[2] = n[0] * m[2] + n[1] * m[1] + n[2] * m[0]
|
||||
r[3] = n[1] * m[2] + n[2] * m[1]
|
||||
r[4] = n[2] * m[2]
|
||||
r[5] = 0 (This is used later to hold spillover from r[4], see tidying in
|
||||
the reduction section.)
|
||||
|
||||
Addition
|
||||
--------
|
||||
Addition is done term by term. The only caveat is to be careful with
|
||||
the number of terms that need to be added. When adding results of
|
||||
multiplication (before reduction), twice as many terms need to be added
|
||||
together. This is done in the addLong function.
|
||||
e.g. for double n[4], m[4], r[4]: r = n + m
|
||||
r[0] = n[0] + m[0]
|
||||
r[1] = n[1] + m[1]
|
||||
r[2] = n[2] + m[2]
|
||||
r[3] = n[3] + m[3]
|
||||
|
||||
Modular Reduction
|
||||
-----------------
|
||||
For the curves implemented, reduction is possible by fast reduction
|
||||
for Generalized Mersenne Primes, as described in [4]. For the
|
||||
floating point implementation, a significant step of the reduction
|
||||
process is tidying: that is, the propagation of carry bits from
|
||||
low-order to high-order coefficients to reduce the precision of each
|
||||
coefficient to 24 bits.
|
||||
This is done by adding and then subtracting
|
||||
ecfp_alpha, a large floating point number that induces precision roundoff.
|
||||
See [5] for more details on tidying using floating point arithmetic.
|
||||
e.g. suppose we have r = 961838 * 2^24 + 519308
|
||||
then if we set alpha = 3 * 2^51 * 2^24,
|
||||
FP(FP(r + alpha) - alpha) = 961838 * 2^24, because the precision for
|
||||
the intermediate results is limited. Our values of alpha are chosen
|
||||
to truncate to a desired number of bits.
|
||||
|
||||
The reduction is then performed as in [4], adding multiples of prime p.
|
||||
e.g. suppose we are working over a polynomial of 10^2. Take the number
|
||||
2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95, stored in 5 elements
|
||||
for coefficients of 10^0, 10^2, ..., 10^8.
|
||||
We wish to reduce modulo p = 10^6 - 2 * 10^4 + 1
|
||||
We can subtract off from the higher terms
|
||||
(2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95) - (2 * 10^2) * (10^6 - 2 * 10^4 + 1)
|
||||
= 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95
|
||||
= 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95 - (15) * (10^6 - 2 * 10^4 + 1)
|
||||
= 83 * 10^4 + 21 * 10^2 + 80
|
||||
|
||||
Integrated Example
|
||||
------------------
|
||||
This example shows how multiplication, addition, tidying, and reduction
|
||||
work together in our modular arithmetic. This is simplified from the
|
||||
actual implementation, but should convey the main concepts.
|
||||
Working over polynomials of 10^2 and with p as in the prior example,
|
||||
Let a = 16 * 10^4 + 53 * 10^2 + 33
|
||||
let b = 81 * 10^4 + 31 * 10^2 + 49
|
||||
let c = 22 * 10^4 + 0 * 10^2 + 95
|
||||
And suppose we want to compute a * b + c mod p.
|
||||
We first do a multiplication: then a * b =
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5100 * 10^4 + 3620 * 10^2 + 1617
|
||||
Then we add in c before doing reduction, allowing us to get a * b + c =
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
We then perform a tidying on the upper half of the terms:
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6
|
||||
0 * 10^10 + (1296 + 47) * 10^8 + 89 * 10^6
|
||||
0 * 10^10 + 1343 * 10^8 + 89 * 10^6
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6
|
||||
which then gives us
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
we then reduce modulo p similar to the reduction example above:
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
- (13 * 10^4 * p)
|
||||
69 * 10^8 + 89 * 10^6 + 5109 * 10^4 + 3620 * 10^2 + 1712
|
||||
- (69 * 10^2 * p)
|
||||
227 * 10^6 + 5109 * 10^4 + 3551 * 10^2 + 1712
|
||||
- (227 * p)
|
||||
5563 * 10^4 + 3551 * 10^2 + 1485
|
||||
finally, we do tidying to get the precision of each term down to 2 digits
|
||||
5563 * 10^4 + 3565 * 10^2 + 85
|
||||
5598 * 10^4 + 65 * 10^2 + 85
|
||||
55 * 10^6 + 98 * 10^4 + 65 * 10^2 + 85
|
||||
and perform another reduction step
|
||||
- (55 * p)
|
||||
208 * 10^4 + 65 * 10^2 + 30
|
||||
There may be a small number of further reductions that could be done at
|
||||
this point, but this is typically done only at the end when converting
|
||||
from floating point to an integer unit representation.
|
||||
|
||||
FLOATING POINT PRECISION
|
||||
========================
|
||||
This section discusses the precision of floating point numbers, which
|
||||
one writing new formulae or a larger bit size should be aware of. The
|
||||
danger is that an intermediate result may be required to store a
|
||||
mantissa larger than 53 bits, which would cause error by rounding off.
|
||||
|
||||
Note that the tidying with IEEE rounding mode set to round-to-even
|
||||
allows negative numbers, which actually reduces the size of the double
|
||||
mantissa to 23 bits - since it rounds the mantissa to the nearest number
|
||||
modulo 2^24, i.e. roughly between -2^23 and 2^23.
|
||||
A multiplication increases the bit size to 2^46 * n, where n is the number
|
||||
of doubles to store a number. For the 224 bit curve, n = 10. This gives
|
||||
doubles of size 5 * 2^47. Adding two of these doubles gives a result
|
||||
of size 5 * 2^48, which is less than 2^53, so this is safe.
|
||||
Similar analysis can be done for other formulae to ensure numbers remain
|
||||
below 2^53.
|
||||
|
||||
Extended-Precision Floating Point
|
||||
---------------------------------
|
||||
Some platforms, notably x86 Linux, may use an extended-precision floating
|
||||
point representation that has a 64-bit mantissa. [6] Although this
|
||||
implementation is optimized for the IEEE standard 53-bit mantissa,
|
||||
it should work with the 64-bit mantissa. A check is done at run-time
|
||||
in the function ec_set_fp_precision that detects if the precision is
|
||||
greater than 53 bits, and runs code for the 64-bit mantissa accordingly.
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
[1] Certicom Corp., "SEC 2: Recommended Elliptic Curve Domain Parameters", Sept. 20, 2000. www.secg.org
|
||||
[2] Sun Microsystems Inc. UltraSPARC III Cu User's Manual, Version 1.0, May 2002, Table 4.4
|
||||
[3] H. Cohen, A. Miyaji, and T. Ono, "Efficient Elliptic Curve Exponentiation Using Mixed Coordinates".
|
||||
[4] Henk C.A. van Tilborg, Generalized Mersenne Prime. http://www.win.tue.nl/~henkvt/GenMersenne.pdf
|
||||
[5] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2.
|
||||
[6] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2 Notes.
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ec2_h_
|
||||
#define __ec2_h_
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses Montgomery projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). */
|
||||
mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* __ec2_h_ */
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 6;
|
||||
|
||||
/* u[5] only has 6 significant bits */
|
||||
z = u[5];
|
||||
u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[3];
|
||||
u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[2] >> 35; /* z only has 29 significant bits */
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[5] = u[4] = u[3] = 0;
|
||||
u[2] ^= z << 35;
|
||||
#else
|
||||
if (MP_USED(r) < 11) {
|
||||
MP_CHECKOK(s_mp_pad(r, 11));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 11;
|
||||
|
||||
/* u[11] only has 6 significant bits */
|
||||
z = u[10];
|
||||
u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[4] ^= (z << 29);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 28) ^ (z >> 29);
|
||||
u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[3] ^= (z << 29);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 28) ^ (z >> 29);
|
||||
u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[2] ^= (z << 29);
|
||||
z = u[7];
|
||||
u[3] ^= (z >> 28) ^ (z >> 29);
|
||||
u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[1] ^= (z << 29);
|
||||
z = u[6];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29);
|
||||
u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[0] ^= (z << 29);
|
||||
z = u[5] >> 3; /* z only has 29 significant bits */
|
||||
u[1] ^= (z >> 25) ^ (z >> 26);
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0;
|
||||
u[5] ^= z << 3;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 3) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
if (MP_USED(a) < 6) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 12) {
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
}
|
||||
MP_USED(r) = 12;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
#endif
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 163-bit curve. Assumes
|
||||
* reduction polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0;
|
||||
mp_digit rm[6];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_163_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
#endif
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
#endif
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
MP_USED(r) = 6;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3);
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1,
|
||||
b3 ^ b0);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6);
|
||||
MP_DIGIT(r, 8) ^= rm[5];
|
||||
MP_DIGIT(r, 7) ^= rm[4];
|
||||
MP_DIGIT(r, 6) ^= rm[3];
|
||||
MP_DIGIT(r, 5) ^= rm[2];
|
||||
MP_DIGIT(r, 4) ^= rm[1];
|
||||
MP_DIGIT(r, 3) ^= rm[0];
|
||||
MP_USED(r) = 12;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 163-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m163(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_163_mod;
|
||||
group->meth->field_mul = &ec_GF2m_163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_163_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 7;
|
||||
|
||||
/* u[6] only has 2 significant bits */
|
||||
z = u[6];
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 63);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 50);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 63);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 50);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 63);
|
||||
z = u[3] >> 1; /* z only has 63 significant bits */
|
||||
u[1] ^= (z >> 49);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 1;
|
||||
#else
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 13;
|
||||
|
||||
/* u[12] only has 2 significant bits */
|
||||
z = u[12];
|
||||
u[6] ^= (z << 14) ^ (z >> 1);
|
||||
u[5] ^= (z << 31);
|
||||
z = u[11];
|
||||
u[6] ^= (z >> 18);
|
||||
u[5] ^= (z << 14) ^ (z >> 1);
|
||||
u[4] ^= (z << 31);
|
||||
z = u[10];
|
||||
u[5] ^= (z >> 18);
|
||||
u[4] ^= (z << 14) ^ (z >> 1);
|
||||
u[3] ^= (z << 31);
|
||||
z = u[9];
|
||||
u[4] ^= (z >> 18);
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 31);
|
||||
z = u[8];
|
||||
u[3] ^= (z >> 18);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 31);
|
||||
z = u[7];
|
||||
u[2] ^= (z >> 18);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 31);
|
||||
z = u[6] >> 1; /* z only has 31 significant bits */
|
||||
u[1] ^= (z >> 17);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[12] = u[11] = u[10] = u[9] = u[8] = u[7] = 0;
|
||||
u[6] ^= z << 1;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
MP_USED(r) = 7;
|
||||
#else
|
||||
if (MP_USED(a) < 7) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
MP_USED(r) = 13;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
#endif
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 193-bit curve. Assumes
|
||||
* reduction polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, b6 = 0, b5 = 0, b4 = 0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_193_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 14));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 8, a6, a5, a4, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b3, b6 ^ b2, b5 ^ b1,
|
||||
b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7);
|
||||
rm[6] ^= MP_DIGIT(r, 6);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 14;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 193-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m193(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_193_mod;
|
||||
group->meth->field_mul = &ec_GF2m_193_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_193_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 8;
|
||||
|
||||
/* u[7] only has 18 significant bits */
|
||||
z = u[7];
|
||||
u[4] ^= (z << 33) ^ (z >> 41);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[6];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 33) ^ (z >> 41);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 31);
|
||||
u[2] ^= (z << 33) ^ (z >> 41);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 31);
|
||||
u[1] ^= (z << 33) ^ (z >> 41);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[3] >> 41; /* z only has 23 significant bits */
|
||||
u[1] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[7] = u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 41;
|
||||
#else
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 15;
|
||||
|
||||
/* u[14] only has 18 significant bits */
|
||||
z = u[14];
|
||||
u[9] ^= (z << 1);
|
||||
u[7] ^= (z >> 9);
|
||||
u[6] ^= (z << 23);
|
||||
z = u[13];
|
||||
u[9] ^= (z >> 31);
|
||||
u[8] ^= (z << 1);
|
||||
u[6] ^= (z >> 9);
|
||||
u[5] ^= (z << 23);
|
||||
z = u[12];
|
||||
u[8] ^= (z >> 31);
|
||||
u[7] ^= (z << 1);
|
||||
u[5] ^= (z >> 9);
|
||||
u[4] ^= (z << 23);
|
||||
z = u[11];
|
||||
u[7] ^= (z >> 31);
|
||||
u[6] ^= (z << 1);
|
||||
u[4] ^= (z >> 9);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[10];
|
||||
u[6] ^= (z >> 31);
|
||||
u[5] ^= (z << 1);
|
||||
u[3] ^= (z >> 9);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 31);
|
||||
u[4] ^= (z << 1);
|
||||
u[2] ^= (z >> 9);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 1);
|
||||
u[1] ^= (z >> 9);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[7] >> 9; /* z only has 23 significant bits */
|
||||
u[3] ^= (z >> 22);
|
||||
u[2] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[14] = u[13] = u[12] = u[11] = u[10] = u[9] = u[8] = 0;
|
||||
u[7] ^= z << 9;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
MP_USED(r) = 8;
|
||||
#else
|
||||
if (MP_USED(a) < 8) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
MP_USED(r) = 15;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[14] = gf2m_SQR0(v[7]);
|
||||
u[13] = gf2m_SQR1(v[6]);
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
#endif
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 233-bit curve. Assumes
|
||||
* reduction polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a7 = 0, a6 = 0, a5 = 0, a4 = 0, b7 = 0, b6 = 0, b5 = 0, b4 =
|
||||
0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_233_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
b7 = MP_DIGIT(b, 7);
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 16));
|
||||
s_bmul_4x4(MP_DIGITS(r) + 8, a7, a6, a5, a4, b7, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a7 ^ a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b7 ^ b3,
|
||||
b6 ^ b2, b5 ^ b1, b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7) ^ MP_DIGIT(r, 15);
|
||||
rm[6] ^= MP_DIGIT(r, 6) ^ MP_DIGIT(r, 14);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 16;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 233-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m233(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_233_mod;
|
||||
group->meth->field_mul = &ec_GF2m_233_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_233_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.2. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda));
|
||||
MP_CHECKOK(mp_init(&tempx));
|
||||
MP_CHECKOK(mp_init(&tempy));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py+qy) / (px+qx), tempx = a + lambda^2
|
||||
* + lambda + px + qx */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, qx, &tempx, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qx = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = qx + qy / qx */
|
||||
MP_CHECKOK(group->meth->field_div(qy, qx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&lambda, qx, &lambda, group->meth));
|
||||
/* tempx = a + lambda^2 + lambda */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
}
|
||||
/* ry = (qx + tempx) * lambda + tempx + qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempy, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&tempy, qy, ry, group->meth));
|
||||
/* rx = tempx */
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy));
|
||||
/* nqy = qx+qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth));
|
||||
MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group));
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return group->point_add(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err
|
||||
ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl));
|
||||
MP_CHECKOK(mp_init(&accr));
|
||||
MP_CHECKOK(mp_init(&tmp));
|
||||
MP_CHECKOK(mp_init(&pxt));
|
||||
MP_CHECKOK(mp_init(&pyt));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 + x*y */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x^2 + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
|
||||
if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery
|
||||
* projective coordinates. Uses algorithm Mdouble in appendix of Lopez, J.
|
||||
* and Dahab, R. "Fast multiplication on elliptic curves over GF(2^m)
|
||||
* without precomputation". modified to not require precomputation of
|
||||
* c=b^{2^{m-1}}. */
|
||||
static mp_err
|
||||
gf2m_Mdouble(mp_int *x, mp_int *z, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x, &t1, z, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x, &t1, x, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in
|
||||
* Montgomery projective coordinates. Uses algorithm Madd in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". */
|
||||
static mp_err
|
||||
gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1, t2;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&t2) = 0;
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
MP_CHECKOK(mp_init(&t2));
|
||||
|
||||
MP_CHECKOK(mp_copy(x, &t1));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
mp_clear(&t2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". Returns: 0 on error 1 if return value
|
||||
* should be the point at infinity 2 otherwise */
|
||||
static int
|
||||
gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
|
||||
mp_int *x2, mp_int *z2, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int ret = 0;
|
||||
mp_int t3, t4, t5;
|
||||
|
||||
MP_DIGITS(&t3) = 0;
|
||||
MP_DIGITS(&t4) = 0;
|
||||
MP_DIGITS(&t5) = 0;
|
||||
MP_CHECKOK(mp_init(&t3));
|
||||
MP_CHECKOK(mp_init(&t4));
|
||||
MP_CHECKOK(mp_init(&t5));
|
||||
|
||||
if (mp_cmp_z(z1) == 0) {
|
||||
mp_zero(x2);
|
||||
mp_zero(z2);
|
||||
ret = 1;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_z(z2) == 0) {
|
||||
MP_CHECKOK(mp_copy(x, x2));
|
||||
MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth));
|
||||
ret = 2;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_set_int(&t5, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth));
|
||||
|
||||
ret = 2;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t3);
|
||||
mp_clear(&t4);
|
||||
mp_clear(&t5);
|
||||
if (res == MP_OKAY) {
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast
|
||||
* multiplication on elliptic curves over GF(2^m) without
|
||||
* precomputation". Elliptic curve points P and R can be identical. Uses
|
||||
* Montgomery projective coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int x1, x2, z1, z2;
|
||||
int i, j;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&x1));
|
||||
MP_CHECKOK(mp_init(&x2));
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */
|
||||
MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 =
|
||||
* x1^2 =
|
||||
* px^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2
|
||||
* =
|
||||
* px^4
|
||||
* +
|
||||
* b
|
||||
*/
|
||||
|
||||
/* find top-most bit and go one past it */
|
||||
i = MP_USED(n) - 1;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
while (!(MP_DIGITS(n)[i] & mask)) {
|
||||
mask >>= 1;
|
||||
j--;
|
||||
}
|
||||
mask >>= 1;
|
||||
j--;
|
||||
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
for (; j >= 0; j--) {
|
||||
if (MP_DIGITS(n)[i] & mask) {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group));
|
||||
} else {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group));
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group);
|
||||
if (i == 0) {
|
||||
res = MP_BADARG;
|
||||
goto CLEANUP;
|
||||
} else if (i == 1) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&x2, rx));
|
||||
MP_CHECKOK(mp_copy(&z2, ry));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
||||
@@ -1,369 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* by default, these routines are unused and thus don't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). P and R can share x and y coordinates. Assumes
|
||||
* input is already field-encoded using field_enc, and returns output that
|
||||
* is still field-encoded. */
|
||||
mp_err
|
||||
ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz, py / pz^2) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z1, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z2, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed projective-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (3) from Hankerson, Hernandez, Menezes.
|
||||
* Software Implementation of Elliptic Curve Cryptography Over Binary
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, E, F, G;
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
return ec_GF2m_pt_aff2proj(qx, qy, rx, ry, rz, group);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
return mp_copy(pz, rz);
|
||||
}
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&E) = 0;
|
||||
MP_DIGITS(&F) = 0;
|
||||
MP_DIGITS(&G) = 0;
|
||||
MP_CHECKOK(mp_init(&A));
|
||||
MP_CHECKOK(mp_init(&B));
|
||||
MP_CHECKOK(mp_init(&C));
|
||||
MP_CHECKOK(mp_init(&D));
|
||||
MP_CHECKOK(mp_init(&E));
|
||||
MP_CHECKOK(mp_init(&F));
|
||||
MP_CHECKOK(mp_init(&G));
|
||||
|
||||
/* D = pz^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &D, group->meth));
|
||||
|
||||
/* A = qy * pz^2 + py */
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &D, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&A, py, &A, group->meth));
|
||||
|
||||
/* B = qx * pz + px */
|
||||
MP_CHECKOK(group->meth->field_mul(qx, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&B, px, &B, group->meth));
|
||||
|
||||
/* C = pz * B */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &B, &C, group->meth));
|
||||
|
||||
/* D = B^2 * (C + a * pz^2) (using E as a temporary variable) */
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curvea, &D, &D, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C, &D, &D, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&B, &E, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&E, &D, &D, group->meth));
|
||||
|
||||
/* rz = C^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, rz, group->meth));
|
||||
|
||||
/* E = A * C */
|
||||
MP_CHECKOK(group->meth->field_mul(&A, &C, &E, group->meth));
|
||||
|
||||
/* rx = A^2 + D + E */
|
||||
MP_CHECKOK(group->meth->field_sqr(&A, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &D, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &E, rx, group->meth));
|
||||
|
||||
/* F = rx + qx * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(qx, rz, &F, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &F, &F, group->meth));
|
||||
|
||||
/* G = rx + qy * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(qy, rz, &G, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &G, &G, group->meth));
|
||||
|
||||
/* ry = E * F + rz * G (using G as a temporary variable) */
|
||||
MP_CHECKOK(group->meth->field_mul(rz, &G, &G, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&E, &F, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(ry, &G, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&E);
|
||||
mp_clear(&F);
|
||||
mp_clear(&G);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* projective coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* Uses equation (3) from Hankerson, Hernandez, Menezes. Software
|
||||
* Implementation of Elliptic Curve Cryptography Over Binary Fields.
|
||||
*/
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1;
|
||||
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
return ec_GF2m_pt_set_inf_proj(rx, ry, rz);
|
||||
}
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t0));
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
|
||||
/* t0 = px^2 */
|
||||
/* t1 = pz^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &t1, group->meth));
|
||||
|
||||
/* rz = px^2 * pz^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, rz, group->meth));
|
||||
|
||||
/* t0 = px^4 */
|
||||
/* t1 = b * pz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
|
||||
/* rx = px^4 + b * pz^4 */
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t1, rx, group->meth));
|
||||
|
||||
/* ry = b * pz^4 * rz + rx * (a * rz + py^2 + b * pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(ry, &t1, ry, group->meth));
|
||||
/* t0 = a * rz */
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curvea, rz, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(rx, ry, ry, group->meth));
|
||||
/* t1 = b * pz^4 * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(&t1, rz, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t1, ry, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed projective-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 16 * 2], *t;
|
||||
int i, ni, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
t = precomp_arr;
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* x co-ord */
|
||||
MP_SIGN(&precomp[i][0]) = MP_ZPOS;
|
||||
MP_ALLOC(&precomp[i][0]) = ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
MP_USED(&precomp[i][0]) = 1;
|
||||
*t = 0;
|
||||
MP_DIGITS(&precomp[i][0]) = t;
|
||||
t += ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
/* y co-ord */
|
||||
MP_SIGN(&precomp[i][1]) = MP_ZPOS;
|
||||
MP_ALLOC(&precomp[i][1]) = ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
MP_USED(&precomp[i][1]) = 1;
|
||||
*t = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = t;
|
||||
t += ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_proj(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GF2m_pt_add_proj
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GF2m_pt_proj2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int
|
||||
ec_twoTo(int e)
|
||||
{
|
||||
int a = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < e; i++) {
|
||||
a *= 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err
|
||||
ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in, int w)
|
||||
{
|
||||
mp_int k;
|
||||
mp_err res = MP_OKAY;
|
||||
int i, twowm1, mask;
|
||||
|
||||
twowm1 = ec_twoTo(w - 1);
|
||||
mask = 2 * twowm1 - 1;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_CHECKOK(mp_init_copy(&k, in));
|
||||
|
||||
i = 0;
|
||||
/* Compute wNAF form */
|
||||
while (mp_cmp_z(&k) > 0) {
|
||||
if (mp_isodd(&k)) {
|
||||
out[i] = MP_DIGIT(&k, 0) & mask;
|
||||
if (out[i] >= twowm1)
|
||||
out[i] -= 2 * twowm1;
|
||||
|
||||
/* Subtract off out[i]. Note mp_sub_d only works with
|
||||
* unsigned digits */
|
||||
if (out[i] >= 0) {
|
||||
mp_sub_d(&k, out[i], &k);
|
||||
} else {
|
||||
mp_add_d(&k, -(out[i]), &k);
|
||||
}
|
||||
} else {
|
||||
out[i] = 0;
|
||||
}
|
||||
mp_div_2(&k, &k);
|
||||
i++;
|
||||
}
|
||||
/* Zero out the remaining elements of the out array. */
|
||||
for (; i < bitsize + 1; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
return res;
|
||||
|
||||
}
|
||||
@@ -1,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
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecl_exp_h_
|
||||
#define __ecl_exp_h_
|
||||
|
||||
/* Curve field type */
|
||||
typedef enum {
|
||||
ECField_GFp,
|
||||
ECField_GF2m
|
||||
} ECField;
|
||||
|
||||
/* Hexadecimal encoding of curve parameters */
|
||||
struct ECCurveParamsStr {
|
||||
char *text;
|
||||
ECField field;
|
||||
unsigned int size;
|
||||
char *irr;
|
||||
char *curvea;
|
||||
char *curveb;
|
||||
char *genx;
|
||||
char *geny;
|
||||
char *order;
|
||||
int cofactor;
|
||||
};
|
||||
typedef struct ECCurveParamsStr ECCurveParams;
|
||||
|
||||
/* Named curve parameters */
|
||||
typedef enum {
|
||||
|
||||
ECCurve_noName = 0,
|
||||
|
||||
/* NIST prime curves */
|
||||
ECCurve_NIST_P192,
|
||||
ECCurve_NIST_P224,
|
||||
ECCurve_NIST_P256,
|
||||
ECCurve_NIST_P384,
|
||||
ECCurve_NIST_P521,
|
||||
|
||||
/* NIST binary curves */
|
||||
ECCurve_NIST_K163,
|
||||
ECCurve_NIST_B163,
|
||||
ECCurve_NIST_K233,
|
||||
ECCurve_NIST_B233,
|
||||
ECCurve_NIST_K283,
|
||||
ECCurve_NIST_B283,
|
||||
ECCurve_NIST_K409,
|
||||
ECCurve_NIST_B409,
|
||||
ECCurve_NIST_K571,
|
||||
ECCurve_NIST_B571,
|
||||
|
||||
/* ANSI X9.62 prime curves */
|
||||
/* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */
|
||||
ECCurve_X9_62_PRIME_192V2,
|
||||
ECCurve_X9_62_PRIME_192V3,
|
||||
ECCurve_X9_62_PRIME_239V1,
|
||||
ECCurve_X9_62_PRIME_239V2,
|
||||
ECCurve_X9_62_PRIME_239V3,
|
||||
/* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */
|
||||
|
||||
/* ANSI X9.62 binary curves */
|
||||
ECCurve_X9_62_CHAR2_PNB163V1,
|
||||
ECCurve_X9_62_CHAR2_PNB163V2,
|
||||
ECCurve_X9_62_CHAR2_PNB163V3,
|
||||
ECCurve_X9_62_CHAR2_PNB176V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V2,
|
||||
ECCurve_X9_62_CHAR2_TNB191V3,
|
||||
ECCurve_X9_62_CHAR2_PNB208W1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V2,
|
||||
ECCurve_X9_62_CHAR2_TNB239V3,
|
||||
ECCurve_X9_62_CHAR2_PNB272W1,
|
||||
ECCurve_X9_62_CHAR2_PNB304W1,
|
||||
ECCurve_X9_62_CHAR2_TNB359V1,
|
||||
ECCurve_X9_62_CHAR2_PNB368W1,
|
||||
ECCurve_X9_62_CHAR2_TNB431R1,
|
||||
|
||||
/* SEC2 prime curves */
|
||||
ECCurve_SECG_PRIME_112R1,
|
||||
ECCurve_SECG_PRIME_112R2,
|
||||
ECCurve_SECG_PRIME_128R1,
|
||||
ECCurve_SECG_PRIME_128R2,
|
||||
ECCurve_SECG_PRIME_160K1,
|
||||
ECCurve_SECG_PRIME_160R1,
|
||||
ECCurve_SECG_PRIME_160R2,
|
||||
ECCurve_SECG_PRIME_192K1,
|
||||
/* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */
|
||||
ECCurve_SECG_PRIME_224K1,
|
||||
/* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */
|
||||
ECCurve_SECG_PRIME_256K1,
|
||||
/* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */
|
||||
/* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */
|
||||
/* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */
|
||||
|
||||
/* SEC2 binary curves */
|
||||
ECCurve_SECG_CHAR2_113R1,
|
||||
ECCurve_SECG_CHAR2_113R2,
|
||||
ECCurve_SECG_CHAR2_131R1,
|
||||
ECCurve_SECG_CHAR2_131R2,
|
||||
/* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */
|
||||
ECCurve_SECG_CHAR2_163R1,
|
||||
/* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */
|
||||
ECCurve_SECG_CHAR2_193R1,
|
||||
ECCurve_SECG_CHAR2_193R2,
|
||||
/* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */
|
||||
ECCurve_SECG_CHAR2_239K1,
|
||||
/* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */
|
||||
/* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */
|
||||
/* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */
|
||||
/* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */
|
||||
/* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */
|
||||
/* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */
|
||||
|
||||
/* WTLS curves */
|
||||
ECCurve_WTLS_1,
|
||||
/* there is no WTLS 2 curve */
|
||||
/* ECCurve_WTLS_3 == ECCurve_NIST_K163 */
|
||||
/* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */
|
||||
/* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
/* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */
|
||||
/* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */
|
||||
ECCurve_WTLS_8,
|
||||
ECCurve_WTLS_9,
|
||||
/* ECCurve_WTLS_10 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
|
||||
/* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
|
||||
|
||||
ECCurve_pastLastCurve
|
||||
} ECCurveName;
|
||||
|
||||
/* Aliased named curves */
|
||||
|
||||
#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192
|
||||
#define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192
|
||||
#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224
|
||||
#define ECCurve_SECG_PRIME_256R1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_384R1 ECCurve_NIST_P384
|
||||
#define ECCurve_SECG_PRIME_521R1 ECCurve_NIST_P521
|
||||
#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163
|
||||
#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163
|
||||
#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233
|
||||
#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233
|
||||
#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283
|
||||
#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283
|
||||
#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409
|
||||
#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409
|
||||
#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571
|
||||
#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571
|
||||
#define ECCurve_WTLS_3 ECCurve_NIST_K163
|
||||
#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1
|
||||
#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1
|
||||
#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1
|
||||
#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1
|
||||
#define ECCurve_WTLS_10 ECCurve_NIST_K233
|
||||
#define ECCurve_WTLS_11 ECCurve_NIST_B233
|
||||
#define ECCurve_WTLS_12 ECCurve_NIST_P224
|
||||
|
||||
#endif /* __ecl_exp_h_ */
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecl_priv_h_
|
||||
#define __ecl_priv_h_
|
||||
|
||||
#include "ecl.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
|
||||
/* the following needs to go away... */
|
||||
#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
|
||||
#define ECL_SIXTY_FOUR_BIT
|
||||
#else
|
||||
#define ECL_THIRTY_TWO_BIT
|
||||
#endif
|
||||
|
||||
#define ECL_CURVE_DIGITS(curve_size_in_bits) \
|
||||
(((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8))
|
||||
#define ECL_BITS (sizeof(mp_digit)*8)
|
||||
#define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit))
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a. If i >= length(a),
|
||||
* then return 0. (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).) */
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(cin)) + (a1) + (a2); \
|
||||
s = ACCUM(w); \
|
||||
cout = CARRYOUT(w); }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(a1)) - (a2) - (bin); \
|
||||
s = ACCUM(w); \
|
||||
bout = (w >> MP_DIGIT_BIT) & 1; }
|
||||
|
||||
#else
|
||||
/* NOTE,
|
||||
* cin and cout could be the same variable.
|
||||
* bin and bout could be the same variable.
|
||||
* a1 or a2 and s could be the same variable.
|
||||
* don't trash those outputs until their respective inputs have
|
||||
* been read. */
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_digit tmp,sum; \
|
||||
tmp = (a1); \
|
||||
sum = tmp + (a2); \
|
||||
tmp = (sum < tmp); /* detect overflow */ \
|
||||
s = sum += (cin); \
|
||||
cout = tmp + (sum < (cin)); }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_digit tmp; \
|
||||
tmp = (a1); \
|
||||
s = tmp - (a2); \
|
||||
tmp = (s > tmp); /* detect borrow */ \
|
||||
if ((bin) && !s--) tmp++; \
|
||||
bout = tmp; }
|
||||
#endif
|
||||
|
||||
|
||||
struct GFMethodStr;
|
||||
typedef struct GFMethodStr GFMethod;
|
||||
struct GFMethodStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Irreducible that defines the field. For prime fields, this is the
|
||||
* prime p. For binary polynomial fields, this is the bitstring
|
||||
* representation of the irreducible polynomial. */
|
||||
mp_int irr;
|
||||
/* For prime fields, the value irr_arr[0] is the number of bits in the
|
||||
* field. For binary polynomial fields, the irreducible polynomial
|
||||
* f(t) is represented as an array of unsigned int[], where f(t) is
|
||||
* of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0]
|
||||
* > p[1] > ... > p[4] = 0. */
|
||||
unsigned int irr_arr[5];
|
||||
/* Field arithmetic methods. All methods (except field_enc and
|
||||
* field_dec) are assumed to take field-encoded parameters and return
|
||||
* field-encoded values. All methods (except field_enc and field_dec)
|
||||
* are required to be implemented. */
|
||||
mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (GFMethod *meth);
|
||||
};
|
||||
|
||||
/* Construct generic GFMethods. */
|
||||
GFMethod *GFMethod_consGFp(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGFp_mont(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGF2m(const mp_int *irr,
|
||||
const unsigned int irr_arr[5]);
|
||||
/* Free the memory allocated (if any) to a GFMethod object. */
|
||||
void GFMethod_free(GFMethod *meth);
|
||||
|
||||
struct ECGroupStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Field definition and arithmetic. */
|
||||
GFMethod *meth;
|
||||
/* Textual representation of curve name, if any. */
|
||||
char *text;
|
||||
/* Curve parameters, field-encoded. */
|
||||
mp_int curvea, curveb;
|
||||
/* x and y coordinates of the base point, field-encoded. */
|
||||
mp_int genx, geny;
|
||||
/* Order and cofactor of the base point. */
|
||||
mp_int order;
|
||||
int cofactor;
|
||||
/* Point arithmetic methods. All methods are assumed to take
|
||||
* field-encoded parameters and return field-encoded values. All
|
||||
* methods (except base_point_mul and points_mul) are required to be
|
||||
* implemented. */
|
||||
mp_err (*point_add) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_sub) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_mul) (const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (ECGroup *group);
|
||||
};
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* fixed length in-line adds. Count is in words */
|
||||
mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
/* Wrapper functions for generic binary polynomial field arithmetic. */
|
||||
mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* Montgomery prime field arithmetic. */
|
||||
mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
void ec_GFp_extra_free_mont(GFMethod *meth);
|
||||
|
||||
/* point multiplication */
|
||||
mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in,
|
||||
int w);
|
||||
|
||||
/* Optimized field arithmetic */
|
||||
mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp224(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp256(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp521(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gf2m163(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m193(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
|
||||
|
||||
/* Optimized floating-point arithmetic */
|
||||
#ifdef ECL_USE_FP
|
||||
mp_err ec_group_set_secp160r1_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp192_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp224_fp(ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* __ecl_priv_h_ */
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ec2.h"
|
||||
#include "ecp.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Allocate memory for a new ECGroup object. */
|
||||
ECGroup *
|
||||
ECGroup_new()
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group;
|
||||
group = (ECGroup *) malloc(sizeof(ECGroup));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
group->constructed = MP_YES;
|
||||
group->meth = NULL;
|
||||
group->text = NULL;
|
||||
MP_DIGITS(&group->curvea) = 0;
|
||||
MP_DIGITS(&group->curveb) = 0;
|
||||
MP_DIGITS(&group->genx) = 0;
|
||||
MP_DIGITS(&group->geny) = 0;
|
||||
MP_DIGITS(&group->order) = 0;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = NULL;
|
||||
group->validate_point = NULL;
|
||||
group->extra1 = NULL;
|
||||
group->extra2 = NULL;
|
||||
group->extra_free = NULL;
|
||||
MP_CHECKOK(mp_init(&group->curvea));
|
||||
MP_CHECKOK(mp_init(&group->curveb));
|
||||
MP_CHECKOK(mp_init(&group->genx));
|
||||
MP_CHECKOK(mp_init(&group->geny));
|
||||
MP_CHECKOK(mp_init(&group->order));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields with
|
||||
* field arithmetic implemented in Montgomery coordinates. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp_mont(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curvea, &group->curvea, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curveb, &group->curveb, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
/* Construct a generic ECGroup for elliptic curves over binary polynomial
|
||||
* fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],
|
||||
const mp_int *curvea, const mp_int *curveb,
|
||||
const mp_int *genx, const mp_int *geny,
|
||||
const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGF2m(irr, irr_arr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GF2m_pt_add_aff;
|
||||
group->point_sub = &ec_GF2m_pt_sub_aff;
|
||||
group->point_dbl = &ec_GF2m_pt_dbl_aff;
|
||||
group->point_mul = &ec_GF2m_pt_mul_mont;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->validate_point = &ec_GF2m_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Construct ECGroup from hex parameters and name, if any. Called by
|
||||
* ECGroup_fromHex and ECGroup_fromName. */
|
||||
ECGroup *
|
||||
ecgroup_fromNameAndHex(const ECCurveName name,
|
||||
const ECCurveParams * params)
|
||||
{
|
||||
mp_int irr, curvea, curveb, genx, geny, order;
|
||||
int bits;
|
||||
ECGroup *group = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* initialize values */
|
||||
MP_DIGITS(&irr) = 0;
|
||||
MP_DIGITS(&curvea) = 0;
|
||||
MP_DIGITS(&curveb) = 0;
|
||||
MP_DIGITS(&genx) = 0;
|
||||
MP_DIGITS(&geny) = 0;
|
||||
MP_DIGITS(&order) = 0;
|
||||
MP_CHECKOK(mp_init(&irr));
|
||||
MP_CHECKOK(mp_init(&curvea));
|
||||
MP_CHECKOK(mp_init(&curveb));
|
||||
MP_CHECKOK(mp_init(&genx));
|
||||
MP_CHECKOK(mp_init(&geny));
|
||||
MP_CHECKOK(mp_init(&order));
|
||||
MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
|
||||
MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
|
||||
MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
|
||||
MP_CHECKOK(mp_read_radix(&order, params->order, 16));
|
||||
|
||||
/* determine number of bits */
|
||||
bits = mpl_significant_bits(&irr) - 1;
|
||||
if (bits < MP_OKAY) {
|
||||
res = bits;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* determine which optimizations (if any) to use */
|
||||
if (params->field == ECField_GFp) {
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
switch (name) {
|
||||
#ifdef ECL_USE_FP
|
||||
case ECCurve_SECG_PRIME_160R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_secp160r1_fp(group));
|
||||
break;
|
||||
#endif
|
||||
case ECCurve_SECG_PRIME_192R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp192_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp192(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_224R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp224_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp224(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_256R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp256(group, name));
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp521(group, name));
|
||||
break;
|
||||
default:
|
||||
/* use generic arithmetic */
|
||||
#endif
|
||||
group =
|
||||
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
}
|
||||
} else if (params->field == ECField_GF2m) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
if ((name == ECCurve_NIST_K163) ||
|
||||
(name == ECCurve_NIST_B163) ||
|
||||
(name == ECCurve_SECG_CHAR2_163R1)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m163(group, name));
|
||||
} else if ((name == ECCurve_SECG_CHAR2_193R1) ||
|
||||
(name == ECCurve_SECG_CHAR2_193R2)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m193(group, name));
|
||||
} else if ((name == ECCurve_NIST_K233) ||
|
||||
(name == ECCurve_NIST_B233)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m233(group, name));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* set name, if any */
|
||||
if ((group != NULL) && (params->text != NULL)) {
|
||||
group->text = strdup(params->text);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&irr);
|
||||
mp_clear(&curvea);
|
||||
mp_clear(&curveb);
|
||||
mp_clear(&genx);
|
||||
mp_clear(&geny);
|
||||
mp_clear(&order);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromHex(const ECCurveParams * params)
|
||||
{
|
||||
return ecgroup_fromNameAndHex(ECCurve_noName, params);
|
||||
}
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromName(const ECCurveName name)
|
||||
{
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
params = EC_GetNamedCurveParams(name);
|
||||
if (params == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* construct actual group */
|
||||
group = ecgroup_fromNameAndHex(name, params);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py)
|
||||
{
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
return group->validate_point(px, py, group);
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECGroup object. */
|
||||
void
|
||||
ECGroup_free(ECGroup *group)
|
||||
{
|
||||
if (group == NULL)
|
||||
return;
|
||||
GFMethod_free(group->meth);
|
||||
if (group->constructed == MP_NO)
|
||||
return;
|
||||
mp_clear(&group->curvea);
|
||||
mp_clear(&group->curveb);
|
||||
mp_clear(&group->genx);
|
||||
mp_clear(&group->geny);
|
||||
mp_clear(&group->order);
|
||||
if (group->text != NULL)
|
||||
free(group->text);
|
||||
if (group->extra_free != NULL)
|
||||
group->extra_free(group);
|
||||
free(group);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Although this is not an exported header file, code which uses elliptic
|
||||
* curve point operations will need to include it. */
|
||||
|
||||
#ifndef __ecl_h_
|
||||
#define __ecl_h_
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include "mpi.h"
|
||||
|
||||
struct ECGroupStr;
|
||||
typedef struct ECGroupStr ECGroup;
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *ECGroup_fromHex(const ECCurveParams * params);
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *ECGroup_fromName(const ECCurveName name);
|
||||
|
||||
/* Free an allocated ECGroup. */
|
||||
void ECGroup_free(ECGroup *group);
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *ECCurveParams_dup(const ECCurveParams * params);
|
||||
|
||||
/* Free an allocated ECCurveParams */
|
||||
void EC_FreeCurveParams(ECCurveParams * params);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *qx, mp_int *qy);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Input and output values are assumed to
|
||||
* be NOT field-encoded. */
|
||||
mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
|
||||
const mp_int *k2, const mp_int *px, const mp_int *py,
|
||||
mp_int *qx, mp_int *qy);
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62.
|
||||
* Returns MP_YES if the public key is valid, MP_NO if the public key
|
||||
* is invalid, or an error code if the validation could not be
|
||||
* performed. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py);
|
||||
|
||||
#endif /* __ecl_h_ */
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; }
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *
|
||||
ECCurveParams_dup(const ECCurveParams * params)
|
||||
{
|
||||
int res = 1;
|
||||
ECCurveParams *ret = NULL;
|
||||
|
||||
CHECK(ret = (ECCurveParams *) calloc(1, sizeof(ECCurveParams)));
|
||||
if (params->text != NULL) {
|
||||
CHECK(ret->text = strdup(params->text));
|
||||
}
|
||||
ret->field = params->field;
|
||||
ret->size = params->size;
|
||||
if (params->irr != NULL) {
|
||||
CHECK(ret->irr = strdup(params->irr));
|
||||
}
|
||||
if (params->curvea != NULL) {
|
||||
CHECK(ret->curvea = strdup(params->curvea));
|
||||
}
|
||||
if (params->curveb != NULL) {
|
||||
CHECK(ret->curveb = strdup(params->curveb));
|
||||
}
|
||||
if (params->genx != NULL) {
|
||||
CHECK(ret->genx = strdup(params->genx));
|
||||
}
|
||||
if (params->geny != NULL) {
|
||||
CHECK(ret->geny = strdup(params->geny));
|
||||
}
|
||||
if (params->order != NULL) {
|
||||
CHECK(ret->order = strdup(params->order));
|
||||
}
|
||||
ret->cofactor = params->cofactor;
|
||||
|
||||
CLEANUP:
|
||||
if (res != 1) {
|
||||
EC_FreeCurveParams(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *
|
||||
EC_GetNamedCurveParams(const ECCurveName name)
|
||||
{
|
||||
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
|
||||
(ecCurve_map[name] == NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ECCurveParams_dup(ecCurve_map[name]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECCurveParams object. */
|
||||
void
|
||||
EC_FreeCurveParams(ECCurveParams * params)
|
||||
{
|
||||
if (params == NULL)
|
||||
return;
|
||||
if (params->text != NULL)
|
||||
free(params->text);
|
||||
if (params->irr != NULL)
|
||||
free(params->irr);
|
||||
if (params->curvea != NULL)
|
||||
free(params->curvea);
|
||||
if (params->curveb != NULL)
|
||||
free(params->curveb);
|
||||
if (params->genx != NULL)
|
||||
free(params->genx);
|
||||
if (params->geny != NULL)
|
||||
free(params->geny);
|
||||
if (params->order != NULL)
|
||||
free(params->order);
|
||||
free(params);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int kt;
|
||||
|
||||
ARGCHK((k != NULL) && (group != NULL), MP_BADARG);
|
||||
MP_DIGITS(&kt) = 0;
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (mp_cmp(k, &group->order) > 0) {
|
||||
MP_CHECKOK(mp_init(&kt));
|
||||
MP_CHECKOK(mp_mod(k, &group->order, &kt));
|
||||
} else {
|
||||
MP_SIGN(&kt) = MP_ZPOS;
|
||||
MP_USED(&kt) = MP_USED(k);
|
||||
MP_ALLOC(&kt) = MP_ALLOC(k);
|
||||
MP_DIGITS(&kt) = MP_DIGITS(k);
|
||||
}
|
||||
|
||||
if ((px == NULL) || (py == NULL)) {
|
||||
if (group->base_point_mul) {
|
||||
MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group));
|
||||
} else {
|
||||
MP_CHECKOK(group->
|
||||
point_mul(&kt, &group->genx, &group->geny, rx, ry,
|
||||
group));
|
||||
}
|
||||
} else {
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(py, ry, group->meth));
|
||||
MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group));
|
||||
} else {
|
||||
MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group));
|
||||
}
|
||||
}
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if (MP_DIGITS(&kt) != MP_DIGITS(k)) {
|
||||
mp_clear(&kt);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy));
|
||||
MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry));
|
||||
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. Uses
|
||||
* algorithm 15 (simultaneous multiple point multiplication) from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST
|
||||
* Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][0],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS) );
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][1],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS) );
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(group->
|
||||
point_add(rx, ry, &precomp[ai][bi][0],
|
||||
&precomp[ai][bi][1], rx, ry, group));
|
||||
}
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k1t, k2t;
|
||||
const mp_int *k1p, *k2p;
|
||||
|
||||
MP_DIGITS(&k1t) = 0;
|
||||
MP_DIGITS(&k2t) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (k1 != NULL) {
|
||||
if (mp_cmp(k1, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k1t));
|
||||
MP_CHECKOK(mp_mod(k1, &group->order, &k1t));
|
||||
k1p = &k1t;
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
if (k2 != NULL) {
|
||||
if (mp_cmp(k2, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k2t));
|
||||
MP_CHECKOK(mp_mod(k2, &group->order, &k2t));
|
||||
k2p = &k2t;
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
|
||||
/* if points_mul is defined, then use it */
|
||||
if (group->points_mul) {
|
||||
res = group->points_mul(k1p, k2p, px, py, rx, ry, group);
|
||||
} else {
|
||||
res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k1t);
|
||||
mp_clear(&k2t);
|
||||
return res;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecp_h_
|
||||
#define __ecp_h_
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). */
|
||||
mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R(x, y) = k1 * G + k2 * P(x, y), where G is the generator
|
||||
* (base point) of the group of points on the elliptic curve. Allows k1 =
|
||||
* NULL or { k2, P } = NULL. Implemented using mixed Jacobian-affine
|
||||
* coordinates. Input and output values are assumed to be NOT
|
||||
* field-encoded and are in affine form. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
#endif /* __ecp_h_ */
|
||||
@@ -1,516 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP192_DIGITS ECL_CURVE_DIGITS(192)
|
||||
|
||||
/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
mp_digit r3;
|
||||
#ifndef MPI_AMD64_ADD
|
||||
mp_digit carry;
|
||||
#endif
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b;
|
||||
#else
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0;
|
||||
mp_digit r0, r1, r2;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP192_DIGITS) {
|
||||
if (a == r) {
|
||||
return MP_OKAY;
|
||||
}
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECP192_DIGITS*2) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
/* copy out upper words of a */
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
|
||||
/* in all the math below,
|
||||
* nXb is most signifiant, nXa is least significant */
|
||||
switch (a_used) {
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a3a = MP_DIGIT(a, 6);
|
||||
}
|
||||
|
||||
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
MP_ADD_CARRY(r0a, a3a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a3b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a3a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a3b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a4b, r2b, carry, carry);
|
||||
r3 = carry; carry = 0;
|
||||
MP_ADD_CARRY(r0a, a5a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a5b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a5a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a5b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a5a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a5b, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1a, a4a, r1a, 0, carry);
|
||||
MP_ADD_CARRY(r1b, a4b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
MP_ADD_CARRY(r0a, r3, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, r3, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, 0, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 = carry;
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (((r2b == 0xffffffff) && (r2a == 0xffffffff)
|
||||
&& (r1b == 0xffffffff) ) &&
|
||||
((r1a == 0xffffffff) ||
|
||||
(r1a == 0xfffffffe) && (r0a == 0xffffffff) &&
|
||||
(r0b == 0xffffffff)) ) {
|
||||
/* do a quick subtract */
|
||||
MP_ADD_CARRY(r0a, 1, r0a, 0, carry);
|
||||
r0b += carry;
|
||||
r1a = r1b = r2a = r2b = 0;
|
||||
}
|
||||
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
}
|
||||
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, a3, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a4, r2, carry, carry);
|
||||
r3 = carry;
|
||||
MP_ADD_CARRY(r0, a5, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a5, r2, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1, a4, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
#else
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* set the lower words of r */
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq %5,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %6,%0 \n\t"
|
||||
"adcq %6,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %5,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3),
|
||||
"=r"(a4), "=r"(a5)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3),
|
||||
"4" (a3), "5" (a4), "6"(a5)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, r3, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, r3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 = carry;
|
||||
#else
|
||||
a3=r3;
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (r3 || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
/* do a quick subtract */
|
||||
r0++;
|
||||
r1 = r2 = 0;
|
||||
}
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
}
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_USED(r) = 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
/* Compute the sum of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a0 = 0, a1 = 0, a2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit carry;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
a0 = MP_DIGIT(a,0);
|
||||
}
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(a0, r0, r0, 0, carry);
|
||||
MP_ADD_CARRY(a1, r1, r1, carry, carry);
|
||||
MP_ADD_CARRY(a2, r2, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %5,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
|
||||
: "r" (a0), "r" (a1), "r" (a2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'subract' if we've gone over
|
||||
* (add the 2's complement of the curve field) */
|
||||
if (carry || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, 1, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 1, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"addq $1,%0 \n\t"
|
||||
"adcq $1,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the diff of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit b0 = 0, b1 = 0, b2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit borrow;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(a,0);
|
||||
}
|
||||
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
b0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, b0, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"subq %4,%0 \n\t"
|
||||
"sbbq %5,%1 \n\t"
|
||||
"sbbq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow)
|
||||
: "r" (b0), "r" (b1), "r" (b2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'add' if we've gone under 0
|
||||
* (subtract the 2's complement of the curve field) */
|
||||
if (borrow) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, 1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, 0, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"subq $1,%0 \n\t"
|
||||
"sbbq $1,%1 \n\t"
|
||||
"sbbq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p192. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p192.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p192. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp192(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P192) {
|
||||
group->meth->field_mod = &ec_GFp_nistp192_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp192_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp192_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp192_div;
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
group->meth->field_add = &ec_GFp_nistp192_add;
|
||||
group->meth->field_sub = &ec_GFp_nistp192_sub;
|
||||
#endif
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP224_DIGITS ECL_CURVE_DIGITS(224)
|
||||
|
||||
/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
|
||||
int r3b;
|
||||
mp_digit carry;
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6a = 0, a6b = 0,
|
||||
a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
|
||||
#else
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
|
||||
mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP224_DIGITS) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECL_CURVE_DIGITS(224*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 14:
|
||||
a6b = MP_DIGIT(a, 13);
|
||||
case 13:
|
||||
a6a = MP_DIGIT(a, 12);
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
}
|
||||
r3a = MP_DIGIT(a, 6);
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1b, a3b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
|
||||
r3b = carry;
|
||||
MP_ADD_CARRY (r1b, a5b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, 0, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
MP_SUB_BORROW(r0a, a3b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
MP_SUB_BORROW(r0a, a5b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
}
|
||||
|
||||
while (r3b > 0) {
|
||||
int tmp;
|
||||
MP_ADD_CARRY(r1b, r3b, r1b, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
MP_ADD_CARRY(r3a, 0, r3a, carry, carry);
|
||||
}
|
||||
tmp = carry;
|
||||
MP_SUB_BORROW(r0a, r3b, r0a, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
tmp -= carry;
|
||||
}
|
||||
r3b = tmp;
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
mp_digit maxInt = MP_DIGIT_MAX;
|
||||
MP_ADD_CARRY (r0a, 1, r0a, 0, carry);
|
||||
MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
|
||||
MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
|
||||
MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
|
||||
&& (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
|
||||
((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0a, 1, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
r1b = r2a = r2b = r3a = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 7;
|
||||
MP_DIGIT(r, 6) = r3a;
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
#else
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
a6b = a6 >> 32;
|
||||
a6a_a5b = a6 << 32;
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
a5b = a5 >> 32;
|
||||
a6a_a5b |= a5b;
|
||||
a5b = a5b << 32;
|
||||
a5a_a4b = a5 << 32;
|
||||
a5a = a5 & 0xffffffff;
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
a5a_a4b |= a4 >> 32;
|
||||
a4a_a3b = a4 << 32;
|
||||
case 4:
|
||||
a3b = MP_DIGIT(a, 3) >> 32;
|
||||
a4a_a3b |= a3b;
|
||||
a3b = a3b << 32;
|
||||
}
|
||||
|
||||
r3 = MP_DIGIT(a, 3) & 0xffffffff;
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1, a3b, r1, 0, carry);
|
||||
MP_ADD_CARRY (r2, a4 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, a5a, r3, carry, carry);
|
||||
MP_ADD_CARRY (r1, a5b, r1, 0, carry);
|
||||
MP_ADD_CARRY (r2, a6 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, 0, r3, carry, carry);
|
||||
|
||||
MP_SUB_BORROW(r0, a4a_a3b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6b , r3, carry, carry);
|
||||
MP_SUB_BORROW(r0, a6a_a5b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6b , r1, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
|
||||
|
||||
/* if the value is negative, r3 has a 2's complement
|
||||
* high value */
|
||||
r3b = (int)(r3 >>32);
|
||||
while (r3b > 0) {
|
||||
r3 &= 0xffffffff;
|
||||
MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, 0, r3, carry, carry);
|
||||
}
|
||||
MP_SUB_BORROW(r0, r3b, r0, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
MP_ADD_CARRY (r0, 1, r0, 0, carry);
|
||||
MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
|
||||
MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
|
||||
&& ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
|
||||
((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
r2 = r3 = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 4));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
MP_DIGIT(r, 3) = r3;
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p224. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p224.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p224.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p224. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp224(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P224) {
|
||||
group->meth->field_mod = &ec_GFp_nistp224_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp224_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp224_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp224_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r.
|
||||
* Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
mp_digit carry;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a8=0, a9=0, a10=0, a11=0, a12=0, a13=0, a14=0, a15=0;
|
||||
mp_digit r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
int r8; /* must be a signed value ! */
|
||||
#else
|
||||
mp_digit a4=0, a5=0, a6=0, a7=0;
|
||||
mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
int r4; /* must be a signed value ! */
|
||||
#endif
|
||||
/* for polynomials larger than twice the field size
|
||||
* use regular reduction */
|
||||
if (a_bits < 256) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a,r);
|
||||
}
|
||||
if (a_bits > 512) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
switch (a_used) {
|
||||
case 16:
|
||||
a15 = MP_DIGIT(a,15);
|
||||
case 15:
|
||||
a14 = MP_DIGIT(a,14);
|
||||
case 14:
|
||||
a13 = MP_DIGIT(a,13);
|
||||
case 13:
|
||||
a12 = MP_DIGIT(a,12);
|
||||
case 12:
|
||||
a11 = MP_DIGIT(a,11);
|
||||
case 11:
|
||||
a10 = MP_DIGIT(a,10);
|
||||
case 10:
|
||||
a9 = MP_DIGIT(a,9);
|
||||
case 9:
|
||||
a8 = MP_DIGIT(a,8);
|
||||
}
|
||||
|
||||
r0 = MP_DIGIT(a,0);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r4 = MP_DIGIT(a,4);
|
||||
r5 = MP_DIGIT(a,5);
|
||||
r6 = MP_DIGIT(a,6);
|
||||
r7 = MP_DIGIT(a,7);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 = carry;
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r3, a12, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* combine last bottom of sum 3 with second sum 2 */
|
||||
MP_ADD_CARRY(r0, a8, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a9, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a10, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a12, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry); /* from sum 3 */
|
||||
r8 += carry;
|
||||
/* sum 3 (rest of it)*/
|
||||
MP_ADD_CARRY(r6, a14, r6, 0, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 4 (rest of it)*/
|
||||
MP_ADD_CARRY(r0, a9, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a10, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a11, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a13, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a14, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a15, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a13, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a8, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a11, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a12, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a13, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a8, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a10, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a12, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a13, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a14, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a15, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a9, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a11, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a13, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a14, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a15, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a8, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a9, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a10, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a12, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a14, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a15, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a9, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a10, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a11, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a13, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r8 > 0) {
|
||||
mp_digit r8_d = r8;
|
||||
MP_ADD_CARRY(r0, r8_d, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 0, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, -r8_d, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r8 < 0) {
|
||||
mp_digit r8_d = -r8;
|
||||
MP_SUB_BORROW(r0, r8_d, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, -r8_d, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = -carry;
|
||||
}
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,8));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 8;
|
||||
|
||||
MP_DIGIT(r,7) = r7;
|
||||
MP_DIGIT(r,6) = r6;
|
||||
MP_DIGIT(r,5) = r5;
|
||||
MP_DIGIT(r,4) = r4;
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r7 == MP_DIGIT_MAX) &&
|
||||
((r6 > 1) || ((r6 == 1) &&
|
||||
(r5 || r4 || r3 ||
|
||||
((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX)
|
||||
&& (r0 == MP_DIGIT_MAX)))))) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
#ifdef notdef
|
||||
|
||||
|
||||
/* smooth the negatives */
|
||||
while (MP_SIGN(r) != MP_ZPOS) {
|
||||
MP_CHECKOK(mp_add(r, &meth->irr, r));
|
||||
}
|
||||
while (MP_USED(r) > 8) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
/* final reduction if necessary */
|
||||
if (MP_DIGIT(r,7) >= MP_DIGIT(&meth->irr,7)) {
|
||||
if (mp_cmp(r,&meth->irr) != MP_LT) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a,7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a,6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a,5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a,4);
|
||||
}
|
||||
a7l = a7 << 32;
|
||||
a7h = a7 >> 32;
|
||||
a6l = a6 << 32;
|
||||
a6h = a6 >> 32;
|
||||
a5l = a5 << 32;
|
||||
a5h = a5 >> 32;
|
||||
a4l = a4 << 32;
|
||||
a4h = a4 >> 32;
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r0 = MP_DIGIT(a,0);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 = carry;
|
||||
MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r1, a6l, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
MP_ADD_CARRY(r1, a6l, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
|
||||
/* sum 3 */
|
||||
MP_ADD_CARRY(r0, a4, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5l >> 32, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 4 */
|
||||
MP_ADD_CARRY(r0, a4h | a5l, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a7, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a6h | a4l, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a5h | a6l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6h, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, (a4l>>32)|a5l,r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a6, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a4h|(a5h<<32),r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a6h|a7l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7h|a4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a4h|a5l, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6l, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a7, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a4h<<32, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a5, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6h<<32, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r4 > 0) {
|
||||
mp_digit r4_long = r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_ADD_CARRY(r0, r4_long, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, -r4l, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r4 < 0) {
|
||||
mp_digit r4_long = -r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_SUB_BORROW(r0, r4_long, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, -r4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = -carry;
|
||||
}
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,4));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r3 > 0xFFFFFFFF00000001ULL) ||
|
||||
((r3 == 0xFFFFFFFF00000001ULL) &&
|
||||
(r2 || (r1 >> 32)||
|
||||
(r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) {
|
||||
/* very rare, just use mp_sub */
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p256. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p256.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp256_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p256.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p256. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp256(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P256) {
|
||||
group->meth->field_mod = &ec_GFp_nistp256_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp256_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp256_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r.
|
||||
* Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m[10];
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit s[10][12];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 12;
|
||||
MP_USED(&m[i]) = 12;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#else
|
||||
mp_digit s[10][6];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 6;
|
||||
MP_USED(&m[i]) = 6;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = 0;
|
||||
s[1][3] = 0;
|
||||
s[1][4] = MP_DIGIT(a, 21);
|
||||
s[1][5] = MP_DIGIT(a, 22);
|
||||
s[1][6] = MP_DIGIT(a, 23);
|
||||
s[1][7] = 0;
|
||||
s[1][8] = 0;
|
||||
s[1][9] = 0;
|
||||
s[1][10] = 0;
|
||||
s[1][11] = 0;
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+12);
|
||||
}
|
||||
s[3][0] = MP_DIGIT(a, 21);
|
||||
s[3][1] = MP_DIGIT(a, 22);
|
||||
s[3][2] = MP_DIGIT(a, 23);
|
||||
for (i = 3; i < 12; i++) {
|
||||
s[3][i] = MP_DIGIT(a, i+9);
|
||||
}
|
||||
s[4][0] = 0;
|
||||
s[4][1] = MP_DIGIT(a, 23);
|
||||
s[4][2] = 0;
|
||||
s[4][3] = MP_DIGIT(a, 20);
|
||||
for (i = 4; i < 12; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+8);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = 0;
|
||||
s[5][3] = 0;
|
||||
s[5][4] = MP_DIGIT(a, 20);
|
||||
s[5][5] = MP_DIGIT(a, 21);
|
||||
s[5][6] = MP_DIGIT(a, 22);
|
||||
s[5][7] = MP_DIGIT(a, 23);
|
||||
s[5][8] = 0;
|
||||
s[5][9] = 0;
|
||||
s[5][10] = 0;
|
||||
s[5][11] = 0;
|
||||
s[6][0] = MP_DIGIT(a, 20);
|
||||
s[6][1] = 0;
|
||||
s[6][2] = 0;
|
||||
s[6][3] = MP_DIGIT(a, 21);
|
||||
s[6][4] = MP_DIGIT(a, 22);
|
||||
s[6][5] = MP_DIGIT(a, 23);
|
||||
s[6][6] = 0;
|
||||
s[6][7] = 0;
|
||||
s[6][8] = 0;
|
||||
s[6][9] = 0;
|
||||
s[6][10] = 0;
|
||||
s[6][11] = 0;
|
||||
s[7][0] = MP_DIGIT(a, 23);
|
||||
for (i = 1; i < 12; i++) {
|
||||
s[7][i] = MP_DIGIT(a, i+11);
|
||||
}
|
||||
s[8][0] = 0;
|
||||
s[8][1] = MP_DIGIT(a, 20);
|
||||
s[8][2] = MP_DIGIT(a, 21);
|
||||
s[8][3] = MP_DIGIT(a, 22);
|
||||
s[8][4] = MP_DIGIT(a, 23);
|
||||
s[8][5] = 0;
|
||||
s[8][6] = 0;
|
||||
s[8][7] = 0;
|
||||
s[8][8] = 0;
|
||||
s[8][9] = 0;
|
||||
s[8][10] = 0;
|
||||
s[8][11] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = 0;
|
||||
s[9][2] = 0;
|
||||
s[9][3] = MP_DIGIT(a, 23);
|
||||
s[9][4] = MP_DIGIT(a, 23);
|
||||
s[9][5] = 0;
|
||||
s[9][6] = 0;
|
||||
s[9][7] = 0;
|
||||
s[9][8] = 0;
|
||||
s[9][9] = 0;
|
||||
s[9][10] = 0;
|
||||
s[9][11] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#else
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[1][3] = MP_DIGIT(a, 11) >> 32;
|
||||
s[1][4] = 0;
|
||||
s[1][5] = 0;
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+6);
|
||||
}
|
||||
s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32);
|
||||
}
|
||||
s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[4][1] = MP_DIGIT(a, 10) << 32;
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+4);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = MP_DIGIT(a, 10);
|
||||
s[5][3] = MP_DIGIT(a, 11);
|
||||
s[5][4] = 0;
|
||||
s[5][5] = 0;
|
||||
s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32;
|
||||
s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32;
|
||||
s[6][2] = MP_DIGIT(a, 11);
|
||||
s[6][3] = 0;
|
||||
s[6][4] = 0;
|
||||
s[6][5] = 0;
|
||||
s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 1; i < 6; i++) {
|
||||
s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32);
|
||||
}
|
||||
s[8][0] = MP_DIGIT(a, 10) << 32;
|
||||
s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[8][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[8][3] = 0;
|
||||
s[8][4] = 0;
|
||||
s[8][5] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[9][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[9][3] = 0;
|
||||
s[9][4] = 0;
|
||||
s[9][5] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p384. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p384.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p384.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p384. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp384(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P384) {
|
||||
group->meth->field_mod = &ec_GFp_nistp384_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp384_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp384_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP521_DIGITS ECL_CURVE_DIGITS(521)
|
||||
|
||||
/* Fast modular reduction for p521 = 2^521 - 1. a can be r. Uses
|
||||
* algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m1;
|
||||
|
||||
mp_digit s1[ECP521_DIGITS] = { 0 };
|
||||
|
||||
MP_SIGN(&m1) = MP_ZPOS;
|
||||
MP_ALLOC(&m1) = ECP521_DIGITS;
|
||||
MP_USED(&m1) = ECP521_DIGITS;
|
||||
MP_DIGITS(&m1) = s1;
|
||||
|
||||
if (a_bits < 521) {
|
||||
if (a==r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if (a_bits > (521*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#define FIRST_DIGIT (ECP521_DIGITS-1)
|
||||
for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) {
|
||||
s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9)
|
||||
| (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9));
|
||||
}
|
||||
s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9;
|
||||
|
||||
if ( a != r ) {
|
||||
MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS));
|
||||
for (i = 0; i < ECP521_DIGITS; i++) {
|
||||
MP_DIGIT(r,i) = MP_DIGIT(a, i);
|
||||
}
|
||||
}
|
||||
MP_USED(r) = ECP521_DIGITS;
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
|
||||
MP_CHECKOK(s_mp_add(r, &m1));
|
||||
if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) {
|
||||
MP_CHECKOK(s_mp_add_d(r,1));
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
}
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p521. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p521.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p521.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p521. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp521(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P521) {
|
||||
group->meth->field_mod = &ec_GFp_nistp521_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp521_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp521_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp521_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. Assumes input
|
||||
* is already field-encoded using field_enc, and returns output that is
|
||||
* still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, temp, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&temp) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda));
|
||||
MP_CHECKOK(mp_init(&temp));
|
||||
MP_CHECKOK(mp_init(&tempx));
|
||||
MP_CHECKOK(mp_init(&tempy));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py-qy) / (px-qx) */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qy = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = (3qx^2+a) / (2qy) */
|
||||
MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 3));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempx, &temp, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 2));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempx, &tempy, &lambda, group->meth));
|
||||
}
|
||||
/* rx = lambda^2 - px - qx */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
|
||||
/* ry = (x1-x2) * lambda - y1 */
|
||||
MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
MP_CHECKOK(mp_copy(&tempy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&temp);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy));
|
||||
/* nqy = -qy */
|
||||
MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth));
|
||||
res = group->point_add(px, py, qx, &nqy, rx, ry, group);
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err
|
||||
ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl));
|
||||
MP_CHECKOK(mp_init(&accr));
|
||||
MP_CHECKOK(mp_init(&tmp));
|
||||
MP_CHECKOK(mp_init(&pxt));
|
||||
MP_CHECKOK(mp_init(&pyt));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
|
||||
if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
||||
@@ -1,568 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves
|
||||
* using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Performs tidying on a short multi-precision floating point integer (the
|
||||
* lower group->numDoubles floats). */
|
||||
void
|
||||
ecfp_tidyShort(double *t, const EC_group_fp * group)
|
||||
{
|
||||
group->ecfp_tidy(t, group->alpha, group);
|
||||
}
|
||||
|
||||
/* Performs tidying on only the upper float digits of a multi-precision
|
||||
* floating point integer, i.e. the digits beyond the regular length which
|
||||
* are removed in the reduction step. */
|
||||
void
|
||||
ecfp_tidyUpper(double *t, const EC_group_fp * group)
|
||||
{
|
||||
group->ecfp_tidy(t + group->numDoubles,
|
||||
group->alpha + group->numDoubles, group);
|
||||
}
|
||||
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of the
|
||||
* doubles is reduced to the regular precision group->doubleBitSize. This
|
||||
* might result in some float digits being negative. Alternative C version
|
||||
* for portability. */
|
||||
void
|
||||
ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
int i;
|
||||
|
||||
/* Do carrying */
|
||||
for (i = 0; i < group->numDoubles - 1; i++) {
|
||||
q = t[i] + alpha[i + 1];
|
||||
q -= alpha[i + 1];
|
||||
t[i] -= q;
|
||||
t[i + 1] += q;
|
||||
|
||||
/* If we don't assume that truncation rounding is used, then q
|
||||
* might be 2^n bigger than expected (if it rounds up), then t[0]
|
||||
* could be negative and t[1] 2^n larger than expected. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Performs a more mathematically precise "tidying" so that each term is
|
||||
* positive. This is slower than the regular tidying, and is used for
|
||||
* conversion from floating point to integer. */
|
||||
void
|
||||
ecfp_positiveTidy(double *t, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
int i;
|
||||
|
||||
/* Do carrying */
|
||||
for (i = 0; i < group->numDoubles - 1; i++) {
|
||||
/* Subtract beta to force rounding down */
|
||||
q = t[i] - ecfp_beta[i + 1];
|
||||
q += group->alpha[i + 1];
|
||||
q -= group->alpha[i + 1];
|
||||
t[i] -= q;
|
||||
t[i + 1] += q;
|
||||
|
||||
/* Due to subtracting ecfp_beta, we should have each term a
|
||||
* non-negative int */
|
||||
ECFP_ASSERT(t[i] / ecfp_exp[i] ==
|
||||
(unsigned long long) (t[i] / ecfp_exp[i]));
|
||||
ECFP_ASSERT(t[i] >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Converts from a floating point representation into an mp_int. Expects
|
||||
* that d is already reduced. */
|
||||
void
|
||||
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup)
|
||||
{
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
unsigned short i16[(group->primeBitSize + 15) / 16];
|
||||
double q = 1;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* TEST uint32_t z = 0; */
|
||||
unsigned int z = 0;
|
||||
#else
|
||||
uint64_t z = 0;
|
||||
#endif
|
||||
int zBits = 0;
|
||||
int copiedBits = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
mp_digit *out;
|
||||
|
||||
/* Result should always be >= 0, so set sign accordingly */
|
||||
MP_SIGN(mpout) = MP_ZPOS;
|
||||
|
||||
/* Tidy up so we're just dealing with positive numbers */
|
||||
ecfp_positiveTidy(d, group);
|
||||
|
||||
/* We might need to do this reduction step more than once if the
|
||||
* reduction adds smaller terms which carry-over to cause another
|
||||
* reduction. However, this should happen very rarely, if ever,
|
||||
* depending on the elliptic curve. */
|
||||
do {
|
||||
/* Init loop data */
|
||||
z = 0;
|
||||
zBits = 0;
|
||||
q = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
copiedBits = 0;
|
||||
|
||||
/* Might have to do a bit more reduction */
|
||||
group->ecfp_singleReduce(d, group);
|
||||
|
||||
/* Grow the size of the mpint if it's too small */
|
||||
s_mp_grow(mpout, group->numInts);
|
||||
MP_USED(mpout) = group->numInts;
|
||||
out = MP_DIGITS(mpout);
|
||||
|
||||
/* Convert double to 16 bit integers */
|
||||
while (copiedBits < group->primeBitSize) {
|
||||
if (zBits < 16) {
|
||||
z += d[i] * q;
|
||||
i++;
|
||||
ECFP_ASSERT(i < (group->primeBitSize + 15) / 16);
|
||||
zBits += group->doubleBitSize;
|
||||
}
|
||||
i16[j] = z;
|
||||
j++;
|
||||
z >>= 16;
|
||||
zBits -= 16;
|
||||
q *= ecfp_twom16;
|
||||
copiedBits += 16;
|
||||
}
|
||||
} while (z != 0);
|
||||
|
||||
/* Convert 16 bit integers to mp_digit */
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
for (i = 0; i < (group->primeBitSize + 15) / 16; i += 2) {
|
||||
*out = 0;
|
||||
if (i + 1 < (group->primeBitSize + 15) / 16) {
|
||||
*out = i16[i + 1];
|
||||
*out <<= 16;
|
||||
}
|
||||
*out++ += i16[i];
|
||||
}
|
||||
#else /* 64 bit */
|
||||
for (i = 0; i < (group->primeBitSize + 15) / 16; i += 4) {
|
||||
*out = 0;
|
||||
if (i + 3 < (group->primeBitSize + 15) / 16) {
|
||||
*out = i16[i + 3];
|
||||
*out <<= 16;
|
||||
}
|
||||
if (i + 2 < (group->primeBitSize + 15) / 16) {
|
||||
*out += i16[i + 2];
|
||||
*out <<= 16;
|
||||
}
|
||||
if (i + 1 < (group->primeBitSize + 15) / 16) {
|
||||
*out += i16[i + 1];
|
||||
*out <<= 16;
|
||||
}
|
||||
*out++ += i16[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Perform final reduction. mpout should already be the same number
|
||||
* of bits as p, but might not be less than p. Make it so. Since
|
||||
* mpout has the same number of bits as p, and 2p has a larger bit
|
||||
* size, then mpout < 2p, so a single subtraction of p will suffice. */
|
||||
if (mp_cmp(mpout, &ecgroup->meth->irr) >= 0) {
|
||||
mp_sub(mpout, &ecgroup->meth->irr, mpout);
|
||||
}
|
||||
|
||||
/* Shrink the size of the mp_int to the actual used size (required for
|
||||
* mp_cmp_z == 0) */
|
||||
out = MP_DIGITS(mpout);
|
||||
for (i = group->numInts - 1; i > 0; i--) {
|
||||
if (out[i] != 0)
|
||||
break;
|
||||
}
|
||||
MP_USED(mpout) = i + 1;
|
||||
|
||||
/* Should be between 0 and p-1 */
|
||||
ECFP_ASSERT(mp_cmp(mpout, &ecgroup->meth->irr) < 0);
|
||||
ECFP_ASSERT(mp_cmp_z(mpout) >= 0);
|
||||
}
|
||||
|
||||
/* Converts from an mpint into a floating point representation. */
|
||||
void
|
||||
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup)
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
int size;
|
||||
double shift = 1;
|
||||
mp_digit *in;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
/* if debug mode, convert result back using ecfp_fp2i into cmp, then
|
||||
* compare to x. */
|
||||
mp_int cmp;
|
||||
|
||||
MP_DIGITS(&cmp) = NULL;
|
||||
mp_init(&cmp);
|
||||
#endif
|
||||
|
||||
ECFP_ASSERT(group != NULL);
|
||||
|
||||
/* init output to 0 (since we skip over some terms) */
|
||||
for (i = 0; i < group->numDoubles; i++)
|
||||
out[i] = 0;
|
||||
i = 0;
|
||||
|
||||
size = MP_USED(x);
|
||||
in = MP_DIGITS(x);
|
||||
|
||||
/* Copy from int into doubles */
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
while (j < size) {
|
||||
while (group->doubleBitSize * (i + 1) <= 32 * j) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(group->doubleBitSize * i <= 32 * j);
|
||||
out[i] = in[j];
|
||||
out[i] *= shift;
|
||||
shift *= ecfp_two32;
|
||||
j++;
|
||||
}
|
||||
#else
|
||||
while (j < size) {
|
||||
while (group->doubleBitSize * (i + 1) <= 64 * j) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(group->doubleBitSize * i <= 64 * j);
|
||||
out[i] = (in[j] & 0x00000000FFFFFFFF) * shift;
|
||||
|
||||
while (group->doubleBitSize * (i + 1) <= 64 * j + 32) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(24 * i <= 64 * j + 32);
|
||||
out[i] = (in[j] & 0xFFFFFFFF00000000) * shift;
|
||||
|
||||
shift *= ecfp_two64;
|
||||
j++;
|
||||
}
|
||||
#endif
|
||||
/* Realign bits to match double boundaries */
|
||||
ecfp_tidyShort(out, group);
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
/* Convert result back to mp_int, compare to original */
|
||||
ecfp_fp2i(&cmp, out, ecgroup);
|
||||
ECFP_ASSERT(mp_cmp(&cmp, x) == 0);
|
||||
mp_clear(&cmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses Jacobian coordinates. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ecfp_jac_pt precomp[16], r;
|
||||
ecfp_aff_pt p;
|
||||
EC_group_fp *group;
|
||||
|
||||
mp_int rz;
|
||||
int i, ni, d;
|
||||
|
||||
ARGCHK(ecgroup != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
group = (EC_group_fp *) ecgroup->extra1;
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
|
||||
/* init p, da */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||||
|
||||
/* Do precomputation */
|
||||
group->precompute_jac(precomp, &p, group);
|
||||
|
||||
/* Do main body of calculations */
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
|
||||
/* R = 2^4 * R */
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
|
||||
/* R = R + (ni * P) */
|
||||
group->pt_add_jac(&r, &precomp[ni], &r, group);
|
||||
}
|
||||
|
||||
/* Convert back to integer */
|
||||
ecfp_fp2i(rx, r.x, ecgroup);
|
||||
ecfp_fp2i(ry, r.y, ecgroup);
|
||||
ecfp_fp2i(&rz, r.z, ecgroup);
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Uses mixed Jacobian-affine coordinates to perform a point
|
||||
* multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
|
||||
* coordinates (Jacobian coordinates for doubles and affine coordinates
|
||||
* for additions; based on recommendation from Brown et al.). Not very
|
||||
* time efficient but quite space efficient, no precomputation needed.
|
||||
* group contains the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Performs calculations in floating point number format, since
|
||||
* this is faster than the integer operations on the ULTRASPARC III.
|
||||
* Uses left-to-right binary method (double & add) (algorithm 9) for
|
||||
* scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res;
|
||||
mp_int sx, sy, sz;
|
||||
|
||||
ecfp_aff_pt p;
|
||||
ecfp_jac_pt r;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
|
||||
int i, l;
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
MP_CHECKOK(mp_init(&sz));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
res = MP_RANGE;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Convert from integer to floating point */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||||
|
||||
/* Init r to point at infinity */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
/* double and add method */
|
||||
l = mpl_significant_bits(n) - 1;
|
||||
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
|
||||
/* if n_i = 1, then R = R + Q */
|
||||
if (MP_GET_BIT(n, i) != 0) {
|
||||
group->pt_add_jac_aff(&r, &p, &r, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from floating point to integer */
|
||||
ecfp_fp2i(&sx, r.x, ecgroup);
|
||||
ecfp_fp2i(&sy, r.y, ecgroup);
|
||||
ecfp_fp2i(&sz, r.z, ecgroup);
|
||||
|
||||
/* convert result R to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point
|
||||
* multiplication from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy, sz;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
ecfp_chud_pt precomp[16];
|
||||
|
||||
ecfp_aff_pt p;
|
||||
ecfp_jm_pt r;
|
||||
|
||||
signed char naf[group->orderBitSize + 1];
|
||||
int i;
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
MP_CHECKOK(mp_init(&sz));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
res = MP_RANGE;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Convert from integer to floating point */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||||
|
||||
/* Perform precomputation */
|
||||
group->precompute_chud(precomp, &p, group);
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, group->orderBitSize, n, 5);
|
||||
|
||||
/* Init R = pt at infinity */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
/* wNAF method */
|
||||
for (i = group->orderBitSize; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
group->pt_dbl_jm(&r, &r, group);
|
||||
|
||||
if (naf[i] != 0) {
|
||||
group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r,
|
||||
group);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from floating point to integer */
|
||||
ecfp_fp2i(&sx, r.x, ecgroup);
|
||||
ecfp_fp2i(&sy, r.y, ecgroup);
|
||||
ecfp_fp2i(&sz, r.z, ecgroup);
|
||||
|
||||
/* convert result R to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Cleans up extra memory allocated in ECGroup for this implementation. */
|
||||
void
|
||||
ec_GFp_extra_free_fp(ECGroup *group)
|
||||
{
|
||||
if (group->extra1 != NULL) {
|
||||
free(group->extra1);
|
||||
group->extra1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tests what precision floating point arithmetic is set to. This should
|
||||
* be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
|
||||
* (extended precision on x86) and sets it into the EC_group_fp. Returns
|
||||
* either 53 or 64 accordingly. */
|
||||
int
|
||||
ec_set_fp_precision(EC_group_fp * group)
|
||||
{
|
||||
double a = 9007199254740992.0; /* 2^53 */
|
||||
double b = a + 1;
|
||||
|
||||
if (a == b) {
|
||||
group->fpPrecision = 53;
|
||||
group->alpha = ecfp_alpha_53;
|
||||
return 53;
|
||||
}
|
||||
group->fpPrecision = 64;
|
||||
group->alpha = ecfp_alpha_64;
|
||||
return 64;
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecp_fp_h_
|
||||
#define __ecp_fp_h_
|
||||
|
||||
#include "mpi.h"
|
||||
#include "ecl.h"
|
||||
#include "ecp.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "mpi-priv.h"
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Largest number of doubles to store one reduced number in floating
|
||||
* point. Used for memory allocation on the stack. */
|
||||
#define ECFP_MAXDOUBLES 10
|
||||
|
||||
/* For debugging purposes */
|
||||
#ifndef ECL_DEBUG
|
||||
#define ECFP_ASSERT(x)
|
||||
#else
|
||||
#define ECFP_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
/* ECFP_Ti = 2^(i*24) Define as preprocessor constants so we can use in
|
||||
* multiple static constants */
|
||||
#define ECFP_T0 1.0
|
||||
#define ECFP_T1 16777216.0
|
||||
#define ECFP_T2 281474976710656.0
|
||||
#define ECFP_T3 4722366482869645213696.0
|
||||
#define ECFP_T4 79228162514264337593543950336.0
|
||||
#define ECFP_T5 1329227995784915872903807060280344576.0
|
||||
#define ECFP_T6 22300745198530623141535718272648361505980416.0
|
||||
#define ECFP_T7 374144419156711147060143317175368453031918731001856.0
|
||||
#define ECFP_T8 6277101735386680763835789423207666416102355444464034512896.0
|
||||
#define ECFP_T9 105312291668557186697918027683670432318895095400549111254310977536.0
|
||||
#define ECFP_T10 1766847064778384329583297500742918515827483896875618958121606201292619776.0
|
||||
#define ECFP_T11 29642774844752946028434172162224104410437116074403984394101141506025761187823616.0
|
||||
#define ECFP_T12 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056.0
|
||||
#define ECFP_T13 8343699359066055009355553539724812947666814540455674882605631280555545803830627148527195652096.0
|
||||
#define ECFP_T14 139984046386112763159840142535527767382602843577165595931249318810236991948760059086304843329475444736.0
|
||||
#define ECFP_T15 2348542582773833227889480596789337027375682548908319870707290971532209025114608443463698998384768703031934976.0
|
||||
#define ECFP_T16 39402006196394479212279040100143613805079739270465446667948293404245\
|
||||
721771497210611414266254884915640806627990306816.0
|
||||
#define ECFP_T17 66105596879024859895191530803277103982840468296428121928464879527440\
|
||||
5791236311345825189210439715284847591212025023358304256.0
|
||||
#define ECFP_T18 11090678776483259438313656736572334813745748301503266300681918322458\
|
||||
485231222502492159897624416558312389564843845614287315896631296.0
|
||||
#define ECFP_T19 18607071341967536398062689481932916079453218833595342343206149099024\
|
||||
36577570298683715049089827234727835552055312041415509848580169253519\
|
||||
36.0
|
||||
|
||||
#define ECFP_TWO160 1461501637330902918203684832716283019655932542976.0
|
||||
#define ECFP_TWO192 6277101735386680763835789423207666416102355444464034512896.0
|
||||
#define ECFP_TWO224 26959946667150639794667015087019630673637144422540572481103610249216.0
|
||||
|
||||
/* Multiplicative constants */
|
||||
static const double ecfp_two32 = 4294967296.0;
|
||||
static const double ecfp_two64 = 18446744073709551616.0;
|
||||
static const double ecfp_twom16 = .0000152587890625;
|
||||
static const double ecfp_twom128 =
|
||||
.00000000000000000000000000000000000000293873587705571876992184134305561419454666389193021880377187926569604314863681793212890625;
|
||||
static const double ecfp_twom129 =
|
||||
.000000000000000000000000000000000000001469367938527859384960920671527807097273331945965109401885939632848021574318408966064453125;
|
||||
static const double ecfp_twom160 =
|
||||
.0000000000000000000000000000000000000000000000006842277657836020854119773355907793609766904013068924666782559979930620520927053718196475529111921787261962890625;
|
||||
static const double ecfp_twom192 =
|
||||
.000000000000000000000000000000000000000000000000000000000159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625;
|
||||
static const double ecfp_twom224 =
|
||||
.00000000000000000000000000000000000000000000000000000000000000000003709206150687421385731735261547639513367564778757791002453039058917581340095629358997312082723208437536338919136001159027049567384892725385725498199462890625;
|
||||
|
||||
/* ecfp_exp[i] = 2^(i*ECFP_DSIZE) */
|
||||
static const double ecfp_exp[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_T0, ECFP_T1, ECFP_T2, ECFP_T3, ECFP_T4, ECFP_T5,
|
||||
ECFP_T6, ECFP_T7, ECFP_T8, ECFP_T9, ECFP_T10, ECFP_T11,
|
||||
ECFP_T12, ECFP_T13, ECFP_T14, ECFP_T15, ECFP_T16, ECFP_T17, ECFP_T18,
|
||||
ECFP_T19
|
||||
};
|
||||
|
||||
/* 1.1 * 2^52 Uses 2^52 to truncate, the .1 is an extra 2^51 to protect
|
||||
* the 2^52 bit, so that adding alphas to a negative number won't borrow
|
||||
* and empty the important 2^52 bit */
|
||||
#define ECFP_ALPHABASE_53 6755399441055744.0
|
||||
/* Special case: On some platforms, notably x86 Linux, there is an
|
||||
* extended-precision floating point representation with 64-bits of
|
||||
* precision in the mantissa. These extra bits of precision require a
|
||||
* larger value of alpha to truncate, i.e. 1.1 * 2^63. */
|
||||
#define ECFP_ALPHABASE_64 13835058055282163712.0
|
||||
|
||||
/*
|
||||
* ecfp_alpha[i] = 1.5 * 2^(52 + i*ECFP_DSIZE) we add and subtract alpha
|
||||
* to truncate floating point numbers to a certain number of bits for
|
||||
* tidying */
|
||||
static const double ecfp_alpha_53[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_ALPHABASE_53 * ECFP_T0,
|
||||
ECFP_ALPHABASE_53 * ECFP_T1,
|
||||
ECFP_ALPHABASE_53 * ECFP_T2,
|
||||
ECFP_ALPHABASE_53 * ECFP_T3,
|
||||
ECFP_ALPHABASE_53 * ECFP_T4,
|
||||
ECFP_ALPHABASE_53 * ECFP_T5,
|
||||
ECFP_ALPHABASE_53 * ECFP_T6,
|
||||
ECFP_ALPHABASE_53 * ECFP_T7,
|
||||
ECFP_ALPHABASE_53 * ECFP_T8,
|
||||
ECFP_ALPHABASE_53 * ECFP_T9,
|
||||
ECFP_ALPHABASE_53 * ECFP_T10,
|
||||
ECFP_ALPHABASE_53 * ECFP_T11,
|
||||
ECFP_ALPHABASE_53 * ECFP_T12,
|
||||
ECFP_ALPHABASE_53 * ECFP_T13,
|
||||
ECFP_ALPHABASE_53 * ECFP_T14,
|
||||
ECFP_ALPHABASE_53 * ECFP_T15,
|
||||
ECFP_ALPHABASE_53 * ECFP_T16,
|
||||
ECFP_ALPHABASE_53 * ECFP_T17,
|
||||
ECFP_ALPHABASE_53 * ECFP_T18,
|
||||
ECFP_ALPHABASE_53 * ECFP_T19
|
||||
};
|
||||
|
||||
/*
|
||||
* ecfp_alpha[i] = 1.5 * 2^(63 + i*ECFP_DSIZE) we add and subtract alpha
|
||||
* to truncate floating point numbers to a certain number of bits for
|
||||
* tidying */
|
||||
static const double ecfp_alpha_64[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_ALPHABASE_64 * ECFP_T0,
|
||||
ECFP_ALPHABASE_64 * ECFP_T1,
|
||||
ECFP_ALPHABASE_64 * ECFP_T2,
|
||||
ECFP_ALPHABASE_64 * ECFP_T3,
|
||||
ECFP_ALPHABASE_64 * ECFP_T4,
|
||||
ECFP_ALPHABASE_64 * ECFP_T5,
|
||||
ECFP_ALPHABASE_64 * ECFP_T6,
|
||||
ECFP_ALPHABASE_64 * ECFP_T7,
|
||||
ECFP_ALPHABASE_64 * ECFP_T8,
|
||||
ECFP_ALPHABASE_64 * ECFP_T9,
|
||||
ECFP_ALPHABASE_64 * ECFP_T10,
|
||||
ECFP_ALPHABASE_64 * ECFP_T11,
|
||||
ECFP_ALPHABASE_64 * ECFP_T12,
|
||||
ECFP_ALPHABASE_64 * ECFP_T13,
|
||||
ECFP_ALPHABASE_64 * ECFP_T14,
|
||||
ECFP_ALPHABASE_64 * ECFP_T15,
|
||||
ECFP_ALPHABASE_64 * ECFP_T16,
|
||||
ECFP_ALPHABASE_64 * ECFP_T17,
|
||||
ECFP_ALPHABASE_64 * ECFP_T18,
|
||||
ECFP_ALPHABASE_64 * ECFP_T19
|
||||
};
|
||||
|
||||
/* 0.011111111111111111111111 (binary) = 0.5 - 2^25 (24 ones) */
|
||||
#define ECFP_BETABASE 0.4999999701976776123046875
|
||||
|
||||
/*
|
||||
* We subtract beta prior to using alpha to simulate rounding down. We
|
||||
* make this close to 0.5 to round almost everything down, but exactly 0.5
|
||||
* would cause some incorrect rounding. */
|
||||
static const double ecfp_beta[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_BETABASE * ECFP_T0,
|
||||
ECFP_BETABASE * ECFP_T1,
|
||||
ECFP_BETABASE * ECFP_T2,
|
||||
ECFP_BETABASE * ECFP_T3,
|
||||
ECFP_BETABASE * ECFP_T4,
|
||||
ECFP_BETABASE * ECFP_T5,
|
||||
ECFP_BETABASE * ECFP_T6,
|
||||
ECFP_BETABASE * ECFP_T7,
|
||||
ECFP_BETABASE * ECFP_T8,
|
||||
ECFP_BETABASE * ECFP_T9,
|
||||
ECFP_BETABASE * ECFP_T10,
|
||||
ECFP_BETABASE * ECFP_T11,
|
||||
ECFP_BETABASE * ECFP_T12,
|
||||
ECFP_BETABASE * ECFP_T13,
|
||||
ECFP_BETABASE * ECFP_T14,
|
||||
ECFP_BETABASE * ECFP_T15,
|
||||
ECFP_BETABASE * ECFP_T16,
|
||||
ECFP_BETABASE * ECFP_T17,
|
||||
ECFP_BETABASE * ECFP_T18,
|
||||
ECFP_BETABASE * ECFP_T19
|
||||
};
|
||||
|
||||
static const double ecfp_beta_160 = ECFP_BETABASE * ECFP_TWO160;
|
||||
static const double ecfp_beta_192 = ECFP_BETABASE * ECFP_TWO192;
|
||||
static const double ecfp_beta_224 = ECFP_BETABASE * ECFP_TWO224;
|
||||
|
||||
/* Affine EC Point. This is the basic representation (x, y) of an elliptic
|
||||
* curve point. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
} ecfp_aff_pt;
|
||||
|
||||
/* Jacobian EC Point. This coordinate system uses X = x/z^2, Y = y/z^3,
|
||||
* which enables calculations with fewer inversions than affine
|
||||
* coordinates. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
} ecfp_jac_pt;
|
||||
|
||||
/* Chudnovsky Jacobian EC Point. This coordinate system is the same as
|
||||
* Jacobian, except it keeps z^2, z^3 for faster additions. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
double z2[ECFP_MAXDOUBLES];
|
||||
double z3[ECFP_MAXDOUBLES];
|
||||
} ecfp_chud_pt;
|
||||
|
||||
/* Modified Jacobian EC Point. This coordinate system is the same as
|
||||
* Jacobian, except it keeps a*z^4 for faster doublings. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
double az4[ECFP_MAXDOUBLES];
|
||||
} ecfp_jm_pt;
|
||||
|
||||
struct EC_group_fp_str;
|
||||
|
||||
typedef struct EC_group_fp_str EC_group_fp;
|
||||
struct EC_group_fp_str {
|
||||
int fpPrecision; /* Set to number of bits in mantissa, 53
|
||||
* or 64 */
|
||||
int numDoubles;
|
||||
int primeBitSize;
|
||||
int orderBitSize;
|
||||
int doubleBitSize;
|
||||
int numInts;
|
||||
int aIsM3; /* True if curvea == -3 (mod p), then we
|
||||
* can optimize doubling */
|
||||
double curvea[ECFP_MAXDOUBLES];
|
||||
/* Used to truncate a double to the number of bits in the curve */
|
||||
double bitSize_alpha;
|
||||
/* Pointer to either ecfp_alpha_53 or ecfp_alpha_64 */
|
||||
const double *alpha;
|
||||
|
||||
void (*ecfp_singleReduce) (double *r, const EC_group_fp * group);
|
||||
void (*ecfp_reduce) (double *r, double *x, const EC_group_fp * group);
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of
|
||||
* the doubles is reduced to the regular precision ECFP_DSIZE. This
|
||||
* might result in some float digits being negative. */
|
||||
void (*ecfp_tidy) (double *t, const double *alpha,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using coordinate system Jacobian + Affine
|
||||
* -> Jacobian. Input and output should be multi-precision floating
|
||||
* point integers. */
|
||||
void (*pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point doubling in Jacobian coordinates. Input and output
|
||||
* should be multi-precision floating point integers. */
|
||||
void (*pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using Jacobian coordinate system. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void (*pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point doubling in Modified Jacobian coordinates. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void (*pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point doubling using coordinates Affine -> Chudnovsky
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void (*pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using coordinates: Modified Jacobian +
|
||||
* Chudnovsky Jacobian -> Modified Jacobian. Input and output should
|
||||
* be multi-precision floating point integers. */
|
||||
void (*pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
|
||||
ecfp_jm_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point addition using Chudnovsky Jacobian coordinates.
|
||||
* Input and output should be multi-precision floating point integers.
|
||||
*/
|
||||
void (*pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
|
||||
ecfp_chud_pt * r, const EC_group_fp * group);
|
||||
/* Expects out to be an array of size 16 of Chudnovsky Jacobian
|
||||
* points. Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for
|
||||
* -15P, -13P, -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P,
|
||||
* 13P, 15P */
|
||||
void (*precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group);
|
||||
/* Expects out to be an array of size 16 of Jacobian points. Fills in
|
||||
* Chudnovsky Jacobian form (x, y, z), for O, P, 2P, ... 15P */
|
||||
void (*precompute_jac) (ecfp_jac_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group);
|
||||
|
||||
};
|
||||
|
||||
/* Computes r = x*y.
|
||||
* r must be different (point to different memory) than x and y.
|
||||
* Does not tidy or reduce. */
|
||||
void ecfp_multiply(double *r, const double *x, const double *y);
|
||||
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of the
|
||||
* doubles is reduced to the regular precision group->doubleBitSize. This
|
||||
* might result in some float digits being negative. */
|
||||
void ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group);
|
||||
|
||||
/* Performs tidying on only the upper float digits of a multi-precision
|
||||
* floating point integer, i.e. the digits beyond the regular length which
|
||||
* are removed in the reduction step. */
|
||||
void ecfp_tidyUpper(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Performs tidying on a short multi-precision floating point integer (the
|
||||
* lower group->numDoubles floats). */
|
||||
void ecfp_tidyShort(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Performs a more mathematically precise "tidying" so that each term is
|
||||
* positive. This is slower than the regular tidying, and is used for
|
||||
* conversion from floating point to integer. */
|
||||
void ecfp_positiveTidy(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Uses 4-bit window
|
||||
* method. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. The
|
||||
* parameters a, b and p are the elliptic curve coefficients and the prime
|
||||
* that determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates (Jacobian
|
||||
* coordinates for doubles and affine coordinates for additions; based on
|
||||
* recommendation from Brown et al.). Uses window NAF method (algorithm
|
||||
* 11) for scalar-point multiplication from Brown, Hankerson, Lopez,
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup);
|
||||
|
||||
/* Uses mixed Jacobian-affine coordinates to perform a point
|
||||
* multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
|
||||
* coordinates (Jacobian coordinates for doubles and affine coordinates
|
||||
* for additions; based on recommendation from Brown et al.). Not very
|
||||
* time efficient but quite space efficient, no precomputation needed.
|
||||
* group contains the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Performs calculations in floating point number format, since
|
||||
* this is faster than the integer operations on the ULTRASPARC III.
|
||||
* Uses left-to-right binary method (double & add) (algorithm 9) for
|
||||
* scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *ecgroup);
|
||||
|
||||
/* Cleans up extra memory allocated in ECGroup for this implementation. */
|
||||
void ec_GFp_extra_free_fp(ECGroup *group);
|
||||
|
||||
/* Converts from a floating point representation into an mp_int. Expects
|
||||
* that d is already reduced. */
|
||||
void
|
||||
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup);
|
||||
|
||||
/* Converts from an mpint into a floating point representation. */
|
||||
void
|
||||
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup);
|
||||
|
||||
/* Tests what precision floating point arithmetic is set to. This should
|
||||
* be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
|
||||
* (extended precision on x86) and sets it into the EC_group_fp. Returns
|
||||
* either 53 or 64 accordingly. */
|
||||
int ec_set_fp_precision(EC_group_fp * group);
|
||||
|
||||
#endif
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 160
|
||||
#define ECFP_NUMDOUBLES 7
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p, but truncates the number
|
||||
* of bits. */
|
||||
void
|
||||
ecfp160_singleReduce(double *d, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 160);
|
||||
ECFP_ASSERT(ECFP_NUMDOUBLES == 7);
|
||||
|
||||
q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_160;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
d[ECFP_NUMDOUBLES - 1] -= q;
|
||||
d[0] += q * ecfp_twom160;
|
||||
d[1] += q * ecfp_twom129;
|
||||
ecfp_positiveTidy(d, group);
|
||||
|
||||
/* Assertions for the highest order term */
|
||||
ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] / ecfp_exp[ECFP_NUMDOUBLES - 1] ==
|
||||
(unsigned long long) (d[ECFP_NUMDOUBLES - 1] /
|
||||
ecfp_exp[ECFP_NUMDOUBLES - 1]));
|
||||
ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] >= 0);
|
||||
}
|
||||
|
||||
/* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should not already be reduced, i.e. should have
|
||||
* 2*ECFP_NUMDOUBLES significant terms. x and r can be the same, but then
|
||||
* the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp160_reduce(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
|
||||
double x7, x8, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 160);
|
||||
ECFP_ASSERT(ECFP_NUMDOUBLES == 7);
|
||||
|
||||
/* Tidy just the upper bits, the lower bits can wait. */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
/* Assume that this is already tidied so that we have enough extra
|
||||
* bits */
|
||||
x7 = x[7] + x[13] * ecfp_twom129; /* adds bits 15-39 */
|
||||
|
||||
/* Tidy x7, or we won't have enough bits later to add it in */
|
||||
q = x7 + group->alpha[8];
|
||||
q -= group->alpha[8];
|
||||
x7 -= q; /* holds bits 0-24 */
|
||||
x8 = x[8] + q; /* holds bits 0-25 */
|
||||
|
||||
r[6] = x[6] + x[13] * ecfp_twom160 + x[12] * ecfp_twom129; /* adds
|
||||
* bits
|
||||
* 8-39 */
|
||||
r[5] = x[5] + x[12] * ecfp_twom160 + x[11] * ecfp_twom129;
|
||||
r[4] = x[4] + x[11] * ecfp_twom160 + x[10] * ecfp_twom129;
|
||||
r[3] = x[3] + x[10] * ecfp_twom160 + x[9] * ecfp_twom129;
|
||||
r[2] = x[2] + x[9] * ecfp_twom160 + x8 * ecfp_twom129; /* adds bits
|
||||
* 8-40 */
|
||||
r[1] = x[1] + x8 * ecfp_twom160 + x7 * ecfp_twom129; /* adds bits
|
||||
* 8-39 */
|
||||
r[0] = x[0] + x7 * ecfp_twom160;
|
||||
|
||||
/* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions
|
||||
* is accurate plus or minus one. (Rather than tidy all to make it
|
||||
* totally accurate, which is more costly.) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive result */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_160;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] += q * ecfp_twom160;
|
||||
r[1] += q * ecfp_twom129;
|
||||
|
||||
/* Tidy the result */
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_secp160r1_fp(ECGroup *group)
|
||||
{
|
||||
|
||||
EC_group_fp *fpg = NULL;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 161;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp160_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp160_reduce;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp160_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp160_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp160_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp160_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp160_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp160_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp160_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp160_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp160_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO160 * fpg->alpha[0];
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 192
|
||||
#define ECFP_NUMDOUBLES 8
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p. */
|
||||
void
|
||||
ecfp192_singleReduce(double *d, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 192);
|
||||
ECFP_ASSERT(group->numDoubles == 8);
|
||||
|
||||
q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_192;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
d[ECFP_NUMDOUBLES - 1] -= q;
|
||||
d[0] += q * ecfp_twom192;
|
||||
d[2] += q * ecfp_twom128;
|
||||
ecfp_positiveTidy(d, group);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should be be an array of at least 16, and r at least 8 x and
|
||||
* r can be the same, but then the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp_reduce_192(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
double x8, x9, x10, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 192);
|
||||
ECFP_ASSERT(group->numDoubles == 8);
|
||||
|
||||
/* Tidy just the upper portion, the lower part can wait */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
x8 = x[8] + x[14] * ecfp_twom128; /* adds bits 16-40 */
|
||||
x9 = x[9] + x[15] * ecfp_twom128; /* adds bits 16-40 */
|
||||
|
||||
/* Tidy up, or we won't have enough bits later to add it in */
|
||||
|
||||
q = x8 + group->alpha[9];
|
||||
q -= group->alpha[9];
|
||||
x8 -= q;
|
||||
x9 += q;
|
||||
|
||||
q = x9 + group->alpha[10];
|
||||
q -= group->alpha[10];
|
||||
x9 -= q;
|
||||
x10 = x[10] + q;
|
||||
|
||||
r[7] = x[7] + x[15] * ecfp_twom192 + x[13] * ecfp_twom128; /* adds
|
||||
* bits
|
||||
* 0-40 */
|
||||
r[6] = x[6] + x[14] * ecfp_twom192 + x[12] * ecfp_twom128;
|
||||
r[5] = x[5] + x[13] * ecfp_twom192 + x[11] * ecfp_twom128;
|
||||
r[4] = x[4] + x[12] * ecfp_twom192 + x10 * ecfp_twom128;
|
||||
r[3] = x[3] + x[11] * ecfp_twom192 + x9 * ecfp_twom128; /* adds bits
|
||||
* 0-40 */
|
||||
r[2] = x[2] + x10 * ecfp_twom192 + x8 * ecfp_twom128;
|
||||
r[1] = x[1] + x9 * ecfp_twom192; /* adds bits 16-40 */
|
||||
r[0] = x[0] + x8 * ecfp_twom192;
|
||||
|
||||
/*
|
||||
* Tidy up just r[group->numDoubles-2] so that the number of
|
||||
* reductions is accurate plus or minus one. (Rather than tidy all to
|
||||
* make it totally accurate) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[group->numDoubles-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive res */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_192;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] += q * ecfp_twom192;
|
||||
r[2] += q * ecfp_twom128;
|
||||
|
||||
/* Tidy the result */
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_nistp192_fp(ECGroup *group)
|
||||
{
|
||||
EC_group_fp *fpg;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 192;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp192_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp_reduce_192;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp192_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp192_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp192_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp192_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp192_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp192_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp192_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp192_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp192_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO192 * fpg->alpha[0];
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 224
|
||||
#define ECFP_NUMDOUBLES 10
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p. */
|
||||
void
|
||||
ecfp224_singleReduce(double *r, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 224);
|
||||
ECFP_ASSERT(group->numDoubles == 10);
|
||||
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] -= q * ecfp_twom224;
|
||||
r[4] += q * ecfp_twom128;
|
||||
|
||||
ecfp_positiveTidy(r, group);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should be be an array of at least 20, and r at least 10 x
|
||||
* and r can be the same, but then the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp224_reduce(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
|
||||
double x10, x11, x12, x13, x14, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 224);
|
||||
ECFP_ASSERT(group->numDoubles == 10);
|
||||
|
||||
/* Tidy just the upper bits of x. Don't need to tidy the lower ones
|
||||
* yet. */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
x10 = x[10] + x[16] * ecfp_twom128;
|
||||
x11 = x[11] + x[17] * ecfp_twom128;
|
||||
x12 = x[12] + x[18] * ecfp_twom128;
|
||||
x13 = x[13] + x[19] * ecfp_twom128;
|
||||
|
||||
/* Tidy up, or we won't have enough bits later to add it in */
|
||||
q = x10 + group->alpha[11];
|
||||
q -= group->alpha[11];
|
||||
x10 -= q;
|
||||
x11 = x11 + q;
|
||||
|
||||
q = x11 + group->alpha[12];
|
||||
q -= group->alpha[12];
|
||||
x11 -= q;
|
||||
x12 = x12 + q;
|
||||
|
||||
q = x12 + group->alpha[13];
|
||||
q -= group->alpha[13];
|
||||
x12 -= q;
|
||||
x13 = x13 + q;
|
||||
|
||||
q = x13 + group->alpha[14];
|
||||
q -= group->alpha[14];
|
||||
x13 -= q;
|
||||
x14 = x[14] + q;
|
||||
|
||||
r[9] = x[9] + x[15] * ecfp_twom128 - x[19] * ecfp_twom224;
|
||||
r[8] = x[8] + x14 * ecfp_twom128 - x[18] * ecfp_twom224;
|
||||
r[7] = x[7] + x13 * ecfp_twom128 - x[17] * ecfp_twom224;
|
||||
r[6] = x[6] + x12 * ecfp_twom128 - x[16] * ecfp_twom224;
|
||||
r[5] = x[5] + x11 * ecfp_twom128 - x[15] * ecfp_twom224;
|
||||
r[4] = x[4] + x10 * ecfp_twom128 - x14 * ecfp_twom224;
|
||||
r[3] = x[3] - x13 * ecfp_twom224;
|
||||
r[2] = x[2] - x12 * ecfp_twom224;
|
||||
r[1] = x[1] - x11 * ecfp_twom224;
|
||||
r[0] = x[0] - x10 * ecfp_twom224;
|
||||
|
||||
/*
|
||||
* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions
|
||||
* is accurate plus or minus one. (Rather than tidy all to make it
|
||||
* totally accurate) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive res */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] -= q * ecfp_twom224;
|
||||
r[4] += q * ecfp_twom128;
|
||||
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_nistp224_fp(ECGroup *group)
|
||||
{
|
||||
|
||||
EC_group_fp *fpg;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 224;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp224_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp224_reduce;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp224_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp224_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp224_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp224_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp224_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp224_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp224_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp224_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp224_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO224 * fpg->alpha[0];
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,855 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* This source file is meant to be included by other source files
|
||||
* (ecp_fp###.c, where ### is one of 160, 192, 224) and should not
|
||||
* constitute an independent compilation unit. It requires the following
|
||||
* preprocessor definitions be made: ECFP_BSIZE - the number of bits in
|
||||
* the field's prime
|
||||
* ECFP_NUMDOUBLES - the number of doubles to store one
|
||||
* multi-precision integer in floating point
|
||||
|
||||
/* Adds a prefix to a given token to give a unique token name. Prefixes
|
||||
* with "ecfp" + ECFP_BSIZE + "_". e.g. if ECFP_BSIZE = 160, then
|
||||
* PREFIX(hello) = ecfp160_hello This optimization allows static function
|
||||
* linking and compiler loop unrolling without code duplication. */
|
||||
#ifndef PREFIX
|
||||
#define PREFIX(b) PREFIX1(ECFP_BSIZE, b)
|
||||
#define PREFIX1(bsize, b) PREFIX2(bsize, b)
|
||||
#define PREFIX2(bsize, b) ecfp ## bsize ## _ ## b
|
||||
#endif
|
||||
|
||||
/* Returns true iff every double in d is 0. (If d == 0 and it is tidied,
|
||||
* this will be true.) */
|
||||
mp_err PREFIX(isZero) (const double *d) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
if (d[i] != 0)
|
||||
return MP_NO;
|
||||
}
|
||||
return MP_YES;
|
||||
}
|
||||
|
||||
/* Sets the multi-precision floating point number at t = 0 */
|
||||
void PREFIX(zero) (double *t) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
t[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets the multi-precision floating point number at t = 1 */
|
||||
void PREFIX(one) (double *t) {
|
||||
int i;
|
||||
|
||||
t[0] = 1;
|
||||
for (i = 1; i < ECFP_NUMDOUBLES; i++) {
|
||||
t[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z) is at infinity. Uses Jacobian coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_jac) (const ecfp_jac_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_jac) (ecfp_jac_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y) is at infinity. Uses Affine coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_aff) (const ecfp_aff_pt * p) {
|
||||
if (PREFIX(isZero) (p->x) == MP_YES && PREFIX(isZero) (p->y) == MP_YES)
|
||||
return MP_YES;
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
/* Sets the affine point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_aff) (ecfp_aff_pt * p) {
|
||||
PREFIX(zero) (p->x);
|
||||
PREFIX(zero) (p->y);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z, a*z^4) is at infinity. Uses Modified
|
||||
* Jacobian coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_jm) (const ecfp_jm_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Modified Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_jm) (ecfp_jm_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z, z^2, z^3) is at infinity. Uses Chudnovsky
|
||||
* Jacobian coordinates */
|
||||
mp_err PREFIX(pt_is_inf_chud) (const ecfp_chud_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Chudnovsky Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_chud) (ecfp_chud_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Copies a multi-precision floating point number, Setting dest = src */
|
||||
void PREFIX(copy) (double *dest, const double *src) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets dest = -src */
|
||||
void PREFIX(negLong) (double *dest, const double *src) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
dest[i] = -src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets r = -p p = (x, y, z, z2, z3) r = (x, -y, z, z2, z3) Uses
|
||||
* Chudnovsky Jacobian coordinates. */
|
||||
/* TODO reverse order */
|
||||
void PREFIX(pt_neg_chud) (const ecfp_chud_pt * p, ecfp_chud_pt * r) {
|
||||
int i;
|
||||
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->z2, p->z2);
|
||||
PREFIX(copy) (r->z3, p->z3);
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
r->y[i] = -p->y[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise adds first ECFP_NUMDOUBLES
|
||||
* doubles of x and y and stores the result in r. */
|
||||
void PREFIX(addShort) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ + *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise adds first
|
||||
* 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(addLong) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ + *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise subtracts first
|
||||
* ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(subtractShort) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ - *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise subtracts first
|
||||
* 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(subtractLong) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ - *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x*y. Both x and y should be tidied and reduced,
|
||||
* r must be different (point to different memory) than x and y.
|
||||
* Does not tidy or reduce. */
|
||||
void PREFIX(multiply)(double *r, const double *x, const double *y) {
|
||||
int i, j;
|
||||
|
||||
for(j=0;j<ECFP_NUMDOUBLES-1;j++) {
|
||||
r[j] = x[0] * y[j];
|
||||
r[j+(ECFP_NUMDOUBLES-1)] = x[ECFP_NUMDOUBLES-1] * y[j];
|
||||
}
|
||||
r[ECFP_NUMDOUBLES-1] = x[0] * y[ECFP_NUMDOUBLES-1];
|
||||
r[ECFP_NUMDOUBLES-1] += x[ECFP_NUMDOUBLES-1] * y[0];
|
||||
r[2*ECFP_NUMDOUBLES-2] = x[ECFP_NUMDOUBLES-1] * y[ECFP_NUMDOUBLES-1];
|
||||
r[2*ECFP_NUMDOUBLES-1] = 0;
|
||||
|
||||
for(i=1;i<ECFP_NUMDOUBLES-1;i++) {
|
||||
for(j=0;j<ECFP_NUMDOUBLES;j++) {
|
||||
r[i+j] += (x[i] * y[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the square of x and stores the result in r. x should be
|
||||
* tidied & reduced, r will be neither tidied nor reduced.
|
||||
* r should point to different memory than x */
|
||||
void PREFIX(square) (double *r, const double *x) {
|
||||
PREFIX(multiply) (r, x, x);
|
||||
}
|
||||
|
||||
/* Perform a point doubling in Jacobian coordinates. Input and output
|
||||
* should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
|
||||
const EC_group_fp * group) {
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (PREFIX(pt_is_inf_jac) (dp) == MP_YES) {
|
||||
/* Set r = pt at infinity */
|
||||
PREFIX(set_pt_inf_jac) (dr);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Perform typical point doubling operations */
|
||||
|
||||
/* TODO? is it worthwhile to do optimizations for when pz = 1? */
|
||||
|
||||
if (group->aIsM3) {
|
||||
/* When a = -3, M = 3(px - pz^2)(px + pz^2) */
|
||||
PREFIX(square) (t1, dp->z);
|
||||
group->ecfp_reduce(t1, t1, group); /* 2^23 since the negative
|
||||
* rounding buys another bit */
|
||||
PREFIX(addShort) (t0, dp->x, t1); /* 2*2^23 */
|
||||
PREFIX(subtractShort) (t1, dp->x, t1); /* 2 * 2^23 */
|
||||
PREFIX(multiply) (M, t0, t1); /* 40 * 2^46 */
|
||||
PREFIX(addLong) (t0, M, M); /* 80 * 2^46 */
|
||||
PREFIX(addLong) (M, t0, M); /* 120 * 2^46 < 2^53 */
|
||||
group->ecfp_reduce(M, M, group);
|
||||
} else {
|
||||
/* Generic case */
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
PREFIX(square) (t0, dp->x);
|
||||
PREFIX(addLong) (M, t0, t0);
|
||||
PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */
|
||||
PREFIX(square) (M, dp->z);
|
||||
group->ecfp_reduce(M, M, group);
|
||||
PREFIX(square) (t1, M);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (M, t1, group->curvea); /* M = a(pz^4) */
|
||||
PREFIX(addLong) (M, M, t0);
|
||||
group->ecfp_reduce(M, M, group);
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
PREFIX(multiply) (t1, dp->y, dp->z);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(dr->z, t1, group);
|
||||
|
||||
/* t0 = 2y^2 */
|
||||
PREFIX(square) (t0, dp->y);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(addShort) (t0, t0, t0);
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
PREFIX(multiply) (S, dp->x, t0);
|
||||
PREFIX(addLong) (S, S, S);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
PREFIX(square) (t1, M);
|
||||
PREFIX(subtractShort) (t1, t1, S);
|
||||
PREFIX(subtractShort) (t1, t1, S);
|
||||
group->ecfp_reduce(dr->x, t1, group);
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
PREFIX(square) (t1, t0); /* t1 = 4y^4 */
|
||||
PREFIX(subtractShort) (S, S, dr->x);
|
||||
PREFIX(multiply) (t0, M, S);
|
||||
PREFIX(subtractLong) (t0, t0, t1);
|
||||
PREFIX(subtractLong) (t0, t0, t1);
|
||||
group->ecfp_reduce(dr->y, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using coordinate system Jacobian + Affine ->
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void PREFIX(pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group) {
|
||||
/* Temporary storage */
|
||||
double A[2 * ECFP_NUMDOUBLES], B[2 * ECFP_NUMDOUBLES],
|
||||
C[2 * ECFP_NUMDOUBLES], C2[2 * ECFP_NUMDOUBLES],
|
||||
D[2 * ECFP_NUMDOUBLES], C3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p or q */
|
||||
if (PREFIX(pt_is_inf_aff) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
goto CLEANUP;
|
||||
} else if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
/* Since the affine point is not infinity, we can set r->z = 1 */
|
||||
PREFIX(one) (r->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Calculates c = qx * pz^2 - px d = (qy * b - py) rx = d^2 - c^3 + 2
|
||||
* (px * c^2) ry = d * (c-rx) - py*c^3 rz = c * pz */
|
||||
|
||||
/* A = pz^2, B = pz^3 */
|
||||
PREFIX(square) (A, p->z);
|
||||
group->ecfp_reduce(A, A, group);
|
||||
PREFIX(multiply) (B, A, p->z);
|
||||
group->ecfp_reduce(B, B, group);
|
||||
|
||||
/* C = qx * A - px */
|
||||
PREFIX(multiply) (C, q->x, A);
|
||||
PREFIX(subtractShort) (C, C, p->x);
|
||||
group->ecfp_reduce(C, C, group);
|
||||
|
||||
/* D = qy * B - py */
|
||||
PREFIX(multiply) (D, q->y, B);
|
||||
PREFIX(subtractShort) (D, D, p->y);
|
||||
group->ecfp_reduce(D, D, group);
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
PREFIX(square) (C2, C);
|
||||
group->ecfp_reduce(C2, C2, group);
|
||||
PREFIX(multiply) (C3, C2, C);
|
||||
group->ecfp_reduce(C3, C3, group);
|
||||
|
||||
/* rz = A = pz * C */
|
||||
PREFIX(multiply) (A, p->z, C);
|
||||
group->ecfp_reduce(r->z, A, group);
|
||||
|
||||
/* C = px * C^2, untidied, unreduced */
|
||||
PREFIX(multiply) (C, p->x, C2);
|
||||
|
||||
/* A = D^2, untidied, unreduced */
|
||||
PREFIX(square) (A, D);
|
||||
|
||||
/* rx = B = A - C3 - C - C = D^2 - (C^3 + 2 * (px * C^2) */
|
||||
PREFIX(subtractShort) (A, A, C3);
|
||||
PREFIX(subtractLong) (A, A, C);
|
||||
PREFIX(subtractLong) (A, A, C);
|
||||
group->ecfp_reduce(r->x, A, group);
|
||||
|
||||
/* B = py * C3, untidied, unreduced */
|
||||
PREFIX(multiply) (B, p->y, C3);
|
||||
|
||||
/* C = px * C^2 - rx */
|
||||
PREFIX(subtractShort) (C, C, r->x);
|
||||
group->ecfp_reduce(C, C, group);
|
||||
|
||||
/* ry = A = D * C - py * C^3 */
|
||||
PREFIX(multiply) (A, D, C);
|
||||
PREFIX(subtractLong) (A, A, B);
|
||||
group->ecfp_reduce(r->y, A, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using Jacobian coordinate system. Input and
|
||||
* output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group) {
|
||||
|
||||
/* Temporary Storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_jac) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 , S = py * qz^3 */
|
||||
PREFIX(square) (t0, q->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (U, p->x, t0);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
PREFIX(multiply) (t1, t0, q->z);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, p->y, t1);
|
||||
group->ecfp_reduce(S, t0, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U , R = (qy * pz^3 - S) */
|
||||
PREFIX(square) (t0, p->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (H, q->x, t0);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
PREFIX(multiply) (t1, t0, p->z); /* t1 = pz^3 */
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, t1, q->y); /* t0 = qy * pz^3 */
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(R, t0, group);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t0, q->z, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, p->z);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point doubling in Modified Jacobian coordinates. Input and
|
||||
* output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
|
||||
const EC_group_fp * group) {
|
||||
|
||||
/* Temporary storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], T[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
PREFIX(set_pt_inf_jm) (r);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
PREFIX(square) (t0, p->x);
|
||||
PREFIX(addLong) (M, t0, t0);
|
||||
PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */
|
||||
PREFIX(addShort) (t0, t0, p->az4);
|
||||
group->ecfp_reduce(M, t0, group);
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
PREFIX(multiply) (t1, p->y, p->z);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* t0 = 2y^2, U = 8y^4 */
|
||||
PREFIX(square) (t0, p->y);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(addShort) (t0, t0, t0);
|
||||
PREFIX(square) (U, t0);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
PREFIX(addShort) (U, U, U);
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
PREFIX(multiply) (S, p->x, t0);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
PREFIX(addShort) (S, S, S);
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
PREFIX(square) (T, M);
|
||||
PREFIX(subtractShort) (T, T, S);
|
||||
PREFIX(subtractShort) (T, T, S);
|
||||
group->ecfp_reduce(r->x, T, group);
|
||||
|
||||
/* ry = M * (S - rx) - U */
|
||||
PREFIX(subtractShort) (S, S, r->x);
|
||||
PREFIX(multiply) (t0, M, S);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->y, t0, group);
|
||||
|
||||
/* ra*z^4 = 2*U*(apz4) */
|
||||
PREFIX(multiply) (t1, U, p->az4);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(r->az4, t1, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point doubling using coordinates Affine -> Chudnovsky
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void PREFIX(pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
|
||||
const EC_group_fp * group) {
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], twoY2[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = O */
|
||||
if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
|
||||
PREFIX(set_pt_inf_chud) (r);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3(px)^2 + a */
|
||||
PREFIX(square) (t0, p->x);
|
||||
PREFIX(addLong) (t1, t0, t0);
|
||||
PREFIX(addLong) (t1, t1, t0);
|
||||
PREFIX(addShort) (t1, t1, group->curvea);
|
||||
group->ecfp_reduce(M, t1, group);
|
||||
|
||||
/* twoY2 = 2*(py)^2, S = 4(px)(py)^2 */
|
||||
PREFIX(square) (twoY2, p->y);
|
||||
PREFIX(addLong) (twoY2, twoY2, twoY2);
|
||||
group->ecfp_reduce(twoY2, twoY2, group);
|
||||
PREFIX(multiply) (S, p->x, twoY2);
|
||||
PREFIX(addLong) (S, S, S);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
PREFIX(square) (t0, M);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = M(S-rx) - 8y^4 */
|
||||
PREFIX(subtractShort) (t0, S, r->x);
|
||||
PREFIX(multiply) (t1, t0, M);
|
||||
PREFIX(square) (t0, twoY2);
|
||||
PREFIX(subtractLong) (t1, t1, t0);
|
||||
PREFIX(subtractLong) (t1, t1, t0);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
/* rz = 2py */
|
||||
PREFIX(addShort) (r->z, p->y, p->y);
|
||||
|
||||
/* rz2 = rz^2 */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(r->z2, t0, group);
|
||||
|
||||
/* rz3 = rz^3 */
|
||||
PREFIX(multiply) (t0, r->z, r->z2);
|
||||
group->ecfp_reduce(r->z3, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using coordinates: Modified Jacobian +
|
||||
* Chudnovsky Jacobian -> Modified Jacobian. Input and output should be
|
||||
* multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
|
||||
ecfp_jm_pt * r, const EC_group_fp * group) {
|
||||
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES], pz2[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q need to convert
|
||||
* from Chudnovsky form to Modified Jacobian form */
|
||||
if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
PREFIX(square) (t0, q->z2);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, group->curvea);
|
||||
group->ecfp_reduce(r->az4, t1, group);
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Check for point at infinity for q, if so set r = p */
|
||||
if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->az4, p->az4);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 */
|
||||
PREFIX(multiply) (U, p->x, q->z2);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U */
|
||||
PREFIX(square) (t0, p->z);
|
||||
group->ecfp_reduce(pz2, t0, group);
|
||||
PREFIX(multiply) (H, pz2, q->x);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* S = py * qz^3 */
|
||||
PREFIX(multiply) (S, p->y, q->z3);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* R = (qy * z1^3 - s) */
|
||||
PREFIX(multiply) (t0, pz2, p->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (R, t0, q->y);
|
||||
PREFIX(subtractShort) (R, R, S);
|
||||
group->ecfp_reduce(R, R, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t1, q->z, H);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, p->z, t1);
|
||||
group->ecfp_reduce(r->z, t0, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
if (group->aIsM3) { /* a == -3 */
|
||||
/* a(rz^4) = -3 * ((rz^2)^2) */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(square) (t1, t0);
|
||||
PREFIX(addLong) (t0, t1, t1);
|
||||
PREFIX(addLong) (t0, t0, t1);
|
||||
PREFIX(negLong) (t0, t0);
|
||||
group->ecfp_reduce(r->az4, t0, group);
|
||||
} else { /* Generic case */
|
||||
/* a(rz^4) = a * ((rz^2)^2) */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(square) (t1, t0);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, group->curvea, t1);
|
||||
group->ecfp_reduce(r->az4, t0, group);
|
||||
}
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using Chudnovsky Jacobian coordinates. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
|
||||
ecfp_chud_pt * r, const EC_group_fp * group) {
|
||||
|
||||
/* Temporary Storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_chud) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
PREFIX(copy) (r->z2, q->z2);
|
||||
PREFIX(copy) (r->z3, q->z3);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->z2, p->z2);
|
||||
PREFIX(copy) (r->z3, p->z3);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 */
|
||||
PREFIX(multiply) (U, p->x, q->z2);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U */
|
||||
PREFIX(multiply) (H, q->x, p->z2);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* S = py * qz^3 */
|
||||
PREFIX(multiply) (S, p->y, q->z3);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t0, q->z, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, p->z);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* R = (qy * z1^3 - s) */
|
||||
PREFIX(multiply) (t0, q->y, p->z3);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(R, t0, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
/* rz2 = rz^2 */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(r->z2, t0, group);
|
||||
|
||||
/* rz3 = rz^3 */
|
||||
PREFIX(multiply) (t0, r->z, r->z2);
|
||||
group->ecfp_reduce(r->z3, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Expects out to be an array of size 16 of Chudnovsky Jacobian points.
|
||||
* Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for -15P, -13P,
|
||||
* -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P, 13P, 15P */
|
||||
void PREFIX(precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group) {
|
||||
|
||||
ecfp_chud_pt p2;
|
||||
|
||||
/* Set out[8] = P */
|
||||
PREFIX(copy) (out[8].x, p->x);
|
||||
PREFIX(copy) (out[8].y, p->y);
|
||||
PREFIX(one) (out[8].z);
|
||||
PREFIX(one) (out[8].z2);
|
||||
PREFIX(one) (out[8].z3);
|
||||
|
||||
/* Set p2 = 2P */
|
||||
PREFIX(pt_dbl_aff2chud) (p, &p2, group);
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
PREFIX(pt_add_chud) (&out[8], &p2, &out[9], group);
|
||||
PREFIX(pt_add_chud) (&out[9], &p2, &out[10], group);
|
||||
PREFIX(pt_add_chud) (&out[10], &p2, &out[11], group);
|
||||
PREFIX(pt_add_chud) (&out[11], &p2, &out[12], group);
|
||||
PREFIX(pt_add_chud) (&out[12], &p2, &out[13], group);
|
||||
PREFIX(pt_add_chud) (&out[13], &p2, &out[14], group);
|
||||
PREFIX(pt_add_chud) (&out[14], &p2, &out[15], group);
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
PREFIX(pt_neg_chud) (&out[8], &out[7]);
|
||||
PREFIX(pt_neg_chud) (&out[9], &out[6]);
|
||||
PREFIX(pt_neg_chud) (&out[10], &out[5]);
|
||||
PREFIX(pt_neg_chud) (&out[11], &out[4]);
|
||||
PREFIX(pt_neg_chud) (&out[12], &out[3]);
|
||||
PREFIX(pt_neg_chud) (&out[13], &out[2]);
|
||||
PREFIX(pt_neg_chud) (&out[14], &out[1]);
|
||||
PREFIX(pt_neg_chud) (&out[15], &out[0]);
|
||||
}
|
||||
|
||||
/* Expects out to be an array of size 16 of Jacobian points. Fills in
|
||||
* Jacobian form (x, y, z), for O, P, 2P, ... 15P */
|
||||
void PREFIX(precompute_jac) (ecfp_jac_pt * precomp, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group) {
|
||||
int i;
|
||||
|
||||
/* fill precomputation table */
|
||||
/* set precomp[0] */
|
||||
PREFIX(set_pt_inf_jac) (&precomp[0]);
|
||||
/* set precomp[1] */
|
||||
PREFIX(copy) (precomp[1].x, p->x);
|
||||
PREFIX(copy) (precomp[1].y, p->y);
|
||||
if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
|
||||
PREFIX(zero) (precomp[1].z);
|
||||
} else {
|
||||
PREFIX(one) (precomp[1].z);
|
||||
}
|
||||
/* set precomp[2] */
|
||||
group->pt_dbl_jac(&precomp[1], &precomp[2], group);
|
||||
|
||||
/* set rest of precomp */
|
||||
for (i = 3; i < 16; i++) {
|
||||
group->pt_add_jac_aff(&precomp[i - 1], p, &precomp[i], group);
|
||||
}
|
||||
}
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). P and R can share x and y coordinates.
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2, z3;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_DIGITS(&z3) = 0;
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
MP_CHECKOK(mp_init(&z3));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz^2, py / pz^3) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
mp_clear(&z3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Jacobian-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (2) from Brown, Hankerson, Lopez, and
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, C2, C3;
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&C2) = 0;
|
||||
MP_DIGITS(&C3) = 0;
|
||||
MP_CHECKOK(mp_init(&A));
|
||||
MP_CHECKOK(mp_init(&B));
|
||||
MP_CHECKOK(mp_init(&C));
|
||||
MP_CHECKOK(mp_init(&D));
|
||||
MP_CHECKOK(mp_init(&C2));
|
||||
MP_CHECKOK(mp_init(&C3));
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&C2);
|
||||
mp_clear(&C3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* This routine implements Point Doubling in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1, M, S;
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&M) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
MP_CHECKOK(mp_init(&t0));
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
MP_CHECKOK(mp_init(&M));
|
||||
MP_CHECKOK(mp_init(&S));
|
||||
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
/* M = 3 * px^2 + a */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&t0, &group->curvea, &M, group->meth));
|
||||
} else if (mp_cmp_int(&group->curvea, -3) == 0) {
|
||||
/* M = 3 * (px + pz^2) * (px - pz^2) */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, &M, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &M, group->meth));
|
||||
} else {
|
||||
/* M = 3 * (px^2) + a * (pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&M, &group->curvea, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &t0, &M, group->meth));
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
/* t0 = 4 * py^2 */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, &t0, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, pz, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
}
|
||||
|
||||
/* S = 4 * px * py^2 = px * (2 * py)^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &t0, &S, group->meth));
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
MP_CHECKOK(group->meth->field_add(&S, &S, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, &t1, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t1, group->meth));
|
||||
if (mp_isodd(&t1)) {
|
||||
MP_CHECKOK(mp_add(&t1, &group->meth->irr, &t1));
|
||||
}
|
||||
MP_CHECKOK(mp_div_2(&t1, &t1));
|
||||
MP_CHECKOK(group->meth->field_sub(&S, rx, &S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&M, &S, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&M, &t1, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
mp_clear(&M);
|
||||
mp_clear(&S);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
int i, ni, d;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Uses mixed Jacobian-affine coordinates. Input and output values are
|
||||
* assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous
|
||||
* multiple point multiplication) from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
mp_int rz;
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
MP_DIGITS(&rz) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][1]));
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1],
|
||||
rx, ry, &rz, group));
|
||||
}
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_SCRATCH 6
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Modified Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *t0, *t1, *M, *S;
|
||||
|
||||
t0 = &scratch[0];
|
||||
t1 = &scratch[1];
|
||||
M = &scratch[2];
|
||||
S = &scratch[3];
|
||||
|
||||
#if MAX_SCRATCH < 4
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth));
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth));
|
||||
|
||||
/* t0 = 2y^2 , t1 = 8y^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth));
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, S, group->meth));
|
||||
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - t1 */
|
||||
MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth));
|
||||
|
||||
/* ra*z^4 = 2*t1*(apz4) */
|
||||
MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth));
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *A, *B, *C, *D, *C2, *C3;
|
||||
|
||||
A = &scratch[0];
|
||||
B = &scratch[1];
|
||||
C = &scratch[2];
|
||||
D = &scratch[3];
|
||||
C2 = &scratch[4];
|
||||
C3 = &scratch[5];
|
||||
|
||||
#if MAX_SCRATCH < 6
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
MP_CHECKOK(mp_copy(paz4, raz4));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(D, A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth));
|
||||
|
||||
/* raz4 = a * rz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz, tpx, tpy;
|
||||
mp_int raz4;
|
||||
mp_int scratch[MAX_SCRATCH];
|
||||
signed char *naf = NULL;
|
||||
int i, orderBitSize;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_DIGITS(&raz4) = 0;
|
||||
MP_DIGITS(&tpx) = 0;
|
||||
MP_DIGITS(&tpy) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_DIGITS(&scratch[i]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
MP_CHECKOK(mp_init(&tpx));
|
||||
MP_CHECKOK(mp_init(&tpy));;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(mp_init(&raz4));
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_CHECKOK(mp_init(&scratch[i]));
|
||||
}
|
||||
|
||||
/* Set out[8] = P */
|
||||
MP_CHECKOK(mp_copy(px, &precomp[8][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[8][1]));
|
||||
|
||||
/* Set (tpx, tpy) = 2P */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
|
||||
group));
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
for (i = 8; i < 15; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
|
||||
&precomp[i + 1][0], &precomp[i + 1][1],
|
||||
group));
|
||||
}
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
for (i = 0; i < 8; i++) {
|
||||
MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_neg(&precomp[15 - i][1], &precomp[i][1],
|
||||
group->meth));
|
||||
}
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
orderBitSize = mpl_significant_bits(&group->order);
|
||||
|
||||
/* Allocate memory for NAF */
|
||||
naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
|
||||
if (naf == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, orderBitSize, n, 5);
|
||||
|
||||
/* wNAF method */
|
||||
for (i = orderBitSize; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
|
||||
&raz4, scratch, group);
|
||||
if (naf[i] != 0) {
|
||||
ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
|
||||
&precomp[(naf[i] + 15) / 2][0],
|
||||
&precomp[(naf[i] + 15) / 2][1], rx, ry,
|
||||
&rz, &raz4, scratch, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
mp_clear(&scratch[i]);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
mp_clear(&tpx);
|
||||
mp_clear(&tpy);
|
||||
mp_clear(&rz);
|
||||
mp_clear(&raz4);
|
||||
free(naf);
|
||||
return res;
|
||||
}
|
||||
@@ -1,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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user