Compare commits

..

7 Commits

Author SHA1 Message Date
thayes%netscape.com
3b8fea000b Fix Solaris break for case-sensitive file name
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72695 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-21 00:12:25 +00:00
javi%netscape.com
51edbc0433 Check this change into my branch so I don't forget about it.
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72687 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-20 23:47:28 +00:00
javi%netscape.com
a6665f86d6 fuxing screw up
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72674 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-20 18:54:57 +00:00
javi%netscape.com
e1e34537e6 Fixing a screw-up.
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72673 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-20 18:44:05 +00:00
javi%netscape.com
9613e128d9 Removing type-o mistake
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72672 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-20 18:43:19 +00:00
javi%netscape.com
1f3f975c7b Checking in some files to my branch to test w/ Terry's tree.
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72671 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-20 18:37:41 +00:00
(no author)
ae4913f28c This commit was manufactured by cvs2svn to create branch 'PSM_GLUE_JAVI'.
git-svn-id: svn://10.0.0.236/branches/PSM_GLUE_JAVI@72643 18797224-902f-48f8-a5cc-f745e15eee43
2000-06-20 07:35:42 +00:00
177 changed files with 8088 additions and 46486 deletions

View File

@@ -0,0 +1,32 @@
#
# 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):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src res
include $(topsrcdir)/config/rules.mk

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,27 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..
include <$(DEPTH)/config/config.mak>
DIRS = public src res
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,4 @@
nsIPSMComponent.idl
nsIPSMUIHandler.idl
nsISecureBrowserUI.idl
nsISSLSocketProvider.idl

View File

@@ -0,0 +1,45 @@
#
# 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):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
# Terry Hayes <thayes@netscape.com>
#
MODULE = psmglue
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
XPIDLSRCS = \
nsIPSMComponent.idl \
nsIPSMUIHandler.idl \
nsISecureBrowserUI.idl \
nsIPSMSocketInfo.idl \
nsISSLSocketProvider.idl \
nsISecretDecoderRing.idl \
$(NULL)
PREF_JS_EXPORTS = $(srcdir)/psm-glue.js
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,53 @@
#!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) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
# Terry Hayes <thayes@netscape.com>
#
MODULE = psmglue
DEPTH=..\..\..
IGNORE_MANIFEST=1
DLLNAME = psmglue
PDBFILE = $(DLLNAME).pdb
MAPFILE = $(DLLNAME).map
DLL = .\$(OBJDIR)\$(DLLNAME).dll
MAKE_OBJ_TYPE = DLL
include <$(DEPTH)/config/config.mak>
XPIDL_INCLUDES=-I$(DEPTH)\..\mozilla\dist\idl
XPIDLSRCS= \
.\nsIPSMComponent.idl \
.\nsIPSMUIHandler.idl \
.\nsISecureBrowserUI.idl \
.\nsISSLSocketProvider.idl \
.\nsIPSMSocketInfo.idl \
.\nsISecretDecoderRing.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install::
$(MAKE_INSTALL) .\psm-glue.js $(DIST)\bin\defaults\pref

View File

@@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Mitch Stoltz <mstoltz@netscape.com>
*/
#include "nsISupports.idl"
interface nsIPrincipal;
%{C++
#include "cmtcmn.h"
%}
[ptr] native nsCMTControlStar(CMT_CONTROL);
[scriptable, uuid(9e482670-5412-11d3-bbc8-0000861d1237)]
interface nsIPSMComponent : nsISupports
{
[noscript] nsCMTControlStar getControlConnection( );
/**
* Display the Security Advisor. PickledStatus and hostName can be null.
* If they are, the "Selected Info" dialog will be empty.
*/
void displaySecurityAdvisor(in string pickledStatus, in string hostName);
/**
* This will send PSM all preferences that we know about.
*/
void passPrefs();
};
%{C++
#define PSM_COMPONENT_PROGID "component://netscape/psm"
#define PSM_COMPONENT_CLASSNAME "Mozilla PSM Component"
%}

View File

@@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Doug Turner <dougt@netscape.com>
*/
#include "nsISupports.idl"
%{C++
#include "cmtcmn.h"
#include "nsPSMShimLayer.h"
%}
[ptr] native psmtControlStar(CMT_CONTROL);
[ptr] native cmSocketStar(CMSocket);
[ptr] native nsFileDescStar(PRFileDesc);
[noscript, uuid(deeb8dfc-fb7a-11d3-ac84-00c04fa0d26b)]
interface nsIPSMSocketInfo : nsISupports {
readonly attribute string hostName;
readonly attribute PRInt32 hostPort;
readonly attribute string proxyName;
readonly attribute PRInt32 proxyPort;
readonly attribute psmtControlStar controlPtr;
readonly attribute cmSocketStar socketPtr;
readonly attribute nsFileDescStar fileDescPtr;
void getPickledStatus(out charPtr pickledStatus);
};

View File

@@ -0,0 +1,36 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsISupports.idl"
[scriptable, uuid(d92be9b0-601b-11d3-8c4a-000064657374)]
interface nsIPSMUIHandler : nsISupports
{
void DisplayURI(in long width, in long height, in PRBool modal, in string urlStr);
void PromptForFile(in wstring prompt, in string fileRegEx, in boolean shouldFileExist, out string outFile);
};
%{C++
#define PSM_UI_HANLDER_PROGID "component://netscape/psm/ui"
#define PSM_UI_HANLDER_CLASSNAME "Mozilla PSM UI Handler"
%}

View File

@@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsISocketProvider.idl"
[noscript, uuid(856a93d0-5415-11d3-bbc8-0000861d1237)]
interface nsISSLSocketProvider : nsISocketProvider {
};
%{C++
#define NS_ISSLSOCKETPROVIDER_PROGID NS_NETWORK_SOCKET_PROGID_PREFIX "ssl"
#define NS_ISSLSOCKETPROVIDER_CLASSNAME "Mozilla SSL Socket Provider Component"
%}

View File

@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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):
* thayes@netscape.com
*
*/
#include "nsISupports.idl"
/* Buffer type - for storing 8-bit octet values */
[ptr] native buffer(unsigned char);
[scriptable, uuid(0EC80360-075C-11d4-9FD4-00C04F1B83D8)]
interface nsISecretDecoderRing: nsISupports {
/* Encrypt a buffer - callable only from C++ */
[noscript] long encrypt(in buffer data, in long dataLen, out buffer result);
/* Decrypt a buffer - callable only from C++ */
[noscript] long decrypt(in buffer data, in long dataLen, out buffer result);
/* Encrypt nul-terminated string to BASE64 output */
string encryptString(in string text);
/* Decrypt BASE64 input to nul-terminated string output */
/* There is no check for embedded nul values in the decrypted output */
string decryptString(in string crypt);
/* Prompt the user to change the password on the SDR key */
void changePassword();
/* Logout of the security device that protects the SDR key */
void logout();
};
/*
* Configuration interface for the Secret Decoder Ring
* - this interface allows setting the window that will be
* used as parent for dialog windows (such as password prompts)
*/
[scriptable, uuid(01D8C0F0-0CCC-11d4-9FDD-000064657374)]
interface nsISecretDecoderRingConfig: nsISupports {
void setWindow(in nsISupports w);
};

View File

@@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsISupports.idl"
interface nsIDOMWindow;
interface nsIDOMElement;
[scriptable, uuid(081e31e0-a144-11d3-8c7c-00609792278c)]
interface nsSecureBrowserUI : nsISupports
{
void init(in nsIDOMWindow window, in nsIDOMElement button);
void displayPageInfoUI();
};
%{C++
#define NS_SECURE_BROWSER_UI_PROGID "component://netscape/secure_browser_ui"
#define NS_SECURE_BROWSER_UI_CLASSNAME "Mozilla Secure Browser UI Handler"
#define NS_SECURE_BROWSER_UI_CID \
{ 0x10fe7ea0, 0xa10a, 0x11d3, {0x8c, 0x7c, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c}}
%}

View File

@@ -0,0 +1,11 @@
pref("general.useragent.security", "U");
pref("security.enable_ssl2", true);
pref("security.enable_ssl3", true);
pref("security.default_personal_cert", "Select Automatically");
pref("security.ask_for_password", 0);
pref("security.password_lifetime", 30);
pref("security.warn_entering_secure", true);
pref("security.warn_leaving_secure", true);
pref("security.warn_viewing_mixed", true);
pref("security.warn_submit_insecure", true);

View File

@@ -0,0 +1,32 @@
#
# 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):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = content locale
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,3 @@
securityOverlay.xul
securityUI.js
PSMTaskMenu.xul

View File

@@ -0,0 +1,38 @@
#
# 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):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
COMMUNICATOR_CONTENT_DIR = $(DIST)/bin/chrome/packages/core/communicator/content/
COMMUNICATOR_EXPORT_CONTENT = \
$(srcdir)/securityOverlay.xul \
$(srcdir)/securityUI.js \
$(srcdir)/PSMTaskMenu.xul \
$(NULL)
install::
$(INSTALL) $(COMMUNICATOR_EXPORT_CONTENT) $(COMMUNICATOR_CONTENT_DIR)

View File

@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<!DOCTYPE window SYSTEM "chrome://communicator/locale/PSMTaskMenu.dtd" >
<overlay id="psmTaskMenuID"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script language="JavaScript">
function displaySecurityAdvisor()
{
var psm = Components.classes["component://netscape/psm"].getService();
psm = psm.QueryInterface(Components.interfaces.nsIPSMComponent);
psm.displaySecurityAdvisor( null, null );
}
</script>
<menupopup id="personalManagers">
<menuitem id="PSMMentItem" position="1" value="&PSMCmd.label;" oncommand="displaySecurityAdvisor()"/>
</menupopup>
</overlay>

View File

@@ -0,0 +1,35 @@
#!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):
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) securityOverlay.xul $(DIST)\bin\chrome\packages\core\communicator\content
$(MAKE_INSTALL) securityUI.js $(DIST)\bin\chrome\packages\core\communicator\content
$(MAKE_INSTALL) PSMTaskMenu.xul $(DIST)\bin\chrome\packages\core\communicator\content
clobber::
$(RM) $(DIST)\bin\chrome\packages\core\communicator\content\securityOverlay.xul
$(RM) $(DIST)\bin\chrome\packages\core\communicator\content\securityUI.js
$(RM) $(DIST)\bin\chrome\packages\core\communicator\content\PSMTaskMenu.xul

View File

@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://communicator/skin/securityOverlay.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://communicator/locale/securityOverlay.dtd">
<overlay id="NavSecurityOverlay"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script language="JavaScript" src="chrome://communicator/content/securityUI.js" />
<statusbarpanel id="security-button" onclick="displayPageInfo()" tooltip="aToolTip" tooltiptext="&lockIcon.label;"/>
</overlay>

View File

@@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
window.addEventListener("load", SetSecurityButton, false);
var securityUI;
function SetSecurityButton()
{
dump("in SetSecurityButton\n");
var ui = Components.classes["component://netscape/secure_browser_ui"].createInstance();
securityUI = ui.QueryInterface(Components.interfaces.nsSecureBrowserUI);
var button = document.getElementById('security-button');
if (button && window.content)
securityUI.init(window.content, button);
}
function displayPageInfo()
{
if (securityUI)
securityUI.displayPageInfoUI();
}

View File

@@ -0,0 +1,32 @@
#
# 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):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = en-US
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,3 @@
PSMTaskMenu.dtd
securityOverlay.dtd
security.properties

View File

@@ -0,0 +1,41 @@
#
# 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):
#
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
COMMUNICATOR_RESOURCE_CONTENT = \
$(srcdir)/PSMTaskMenu.dtd \
$(srcdir)/security.properties \
$(srcdir)/securityOverlay.dtd \
$(NULL)
include $(topsrcdir)/config/rules.mk
install::
$(INSTALL) $(COMMUNICATOR_RESOURCE_CONTENT) $(DIST)/bin/chrome/locales/en-US/communicator/locale

View File

@@ -0,0 +1 @@
<!ENTITY PSMCmd.label "Security Manager">

View File

@@ -0,0 +1,37 @@
#!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):
DEPTH=..\..\..\..\..
include <$(DEPTH)\config\rules.mak>
COMMUNICATOR_DIST=$(DIST)\bin\chrome\locales\en-US\communicator\locale
install::
$(MAKE_INSTALL) PSMTaskMenu.dtd $(COMMUNICATOR_DIST)
$(MAKE_INSTALL) security.properties $(COMMUNICATOR_DIST)
$(MAKE_INSTALL) securityOverlay.dtd $(COMMUNICATOR_DIST)
clobber::
$(RM) -f $(DIST)\bin\chrome\locales\en-US\communicator\locale\PSMTaskMenu.dtd
$(RM) -f $(DIST)\bin\chrome\locales\en-US\communicator\locale\security.properties
$(RM) -f $(DIST)\bin\chrome\locales\en-US\communicator\locale\securityOverlay.dtd

View File

@@ -0,0 +1,29 @@
#
# 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):
#
Title=Security Warning
MixedContentMessage=You have requested a secure document that contains some insecure information.
LeaveSiteMessage=You have requested an insecure document. The document and any information you send back could be observed by a third party while in transit.
EnterSiteMessage=You have requested a secure document. The document and any information you send back are encrypted for privacy while in transit.
PostToInsecure=Warning! Although this document is secure, the information you have submitted is insecure and could be observed by a third party while in transit. If you are submitting passwords, credit card numbers, or other information you would like to keep private, it would be safer for you to cancel the submission.
PostToInsecureFromInsecure=Any information you submit is insecure and could be observed by a third party while in transit. If you are submitting passwords, credit card numbers, or other information you would like to keep private, it would be safer for you to cancel the submission.
DontShowAgain=Show Me This Alert Next Time.
FindText=Please find the Personal Security Manager application

View File

@@ -0,0 +1,2 @@
<!ENTITY lockIcon.label "Show security information for this window">

View File

@@ -0,0 +1,27 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..
DIRS=en-US
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,27 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
DIRS = content locale
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,66 @@
#
# 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):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = psmglue
IS_COMPONENT = 1
LIBRARY_NAME = psmglue
CPPSRCS = \
nsPSMComponent.cpp \
nsPSMUICallbacks.cpp \
nsSSLSocketProvider.cpp \
nsPSMModule.cpp \
nsSSLIOLayer.cpp \
nsSecureBrowserUIImpl.cpp \
nsSDR.cpp \
nsFSDR.cpp \
nsCrypto.cpp \
nsKeygenHandler.cpp \
$(NULL)
CSRCS = \
nsPSMMutex.c \
nsPSMShimLayer.c \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
-lcmt \
-lprotocol \
$(MOZ_JS_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir) \
$(NULL)

View File

@@ -0,0 +1,72 @@
#!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) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Hubbie Shaw
# Doug Turner <dougt@netscape.com>
#
MODULE = psmglue
DEPTH=..\..\..
IGNORE_MANIFEST=1
DLLNAME = psmglue
PDBFILE = $(DLLNAME).pdb
MAPFILE = $(DLLNAME).map
DLL = .\$(OBJDIR)\$(DLLNAME).dll
MAKE_OBJ_TYPE = DLL
include <$(DEPTH)/config/config.mak>
LINCS = $(LINCS) \
-I$(PUBLIC) \
-I$(PUBLIC)/security \
$(NULL)
LLIBS = \
$(LIBNSPR) \
$(DIST)\lib\neckobase_s.lib \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\js3250.lib \
$(DIST)\lib\cmt.lib \
$(DIST)\lib\protocol.lib \
$(DIST)\lib\mozreg.lib \
$(DIST)\lib\jsdom.lib \
$(NULL)
OBJS = \
.\$(OBJDIR)\nsPSMMutex.obj \
.\$(OBJDIR)\nsPSMShimLayer.obj \
.\$(OBJDIR)\nsPSMComponent.obj \
.\$(OBJDIR)\nsPSMUICallbacks.obj \
.\$(OBJDIR)\nsPSMModule.obj \
.\$(OBJDIR)\nsSecureBrowserUIImpl.obj \
.\$(OBJDIR)\nsSSLIOLayer.obj \
.\$(OBJDIR)\nsSSLSocketProvider.obj \
.\$(OBJDIR)\nsSDR.obj \
.\$(OBJDIR)\nsFSDR.obj \
.\$(OBJDIR)\nsCrypto.obj \
.\$(OBJDIR)\nsKeygenHandler.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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):
*/
#ifndef _nsCrypto_h_
#define _nsCrypto_h_
#include "nsIDOMCRMFObject.h"
#include "nsIDOMCrypto.h"
#include "nsIScriptObjectOwner.h"
#include "nsIDOMPkcs11.h"
#define NS_CRYPTO_CLASSNAME "Crypto JavaScript Class"
#define NS_CRYPTO_CID \
{0x929d9320, 0x251e, 0x11d4, { 0x8a, 0x7c, 0x00, 0x60, 0x08, 0xc8, 0x44, 0xc3} }
#define NS_PKCS11_CLASSNAME "Pkcs11 JavaScript Class"
#define NS_PKCS11_CID \
{0x74b7a390, 0x3b41, 0x11d4, { 0x8a, 0x80, 0x00, 0x60, 0x08, 0xc8, 0x44, 0xc3} }
class nsIPSMComponent;
class nsIDOMScriptObjectFactory;
class nsCRMFObject : public nsIDOMCRMFObject,
public nsIScriptObjectOwner {
public:
nsCRMFObject();
virtual ~nsCRMFObject();
NS_DECL_IDOMCRMFOBJECT
NS_DECL_ISUPPORTS
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void* aScriptObject);
nsresult init();
nsresult SetCRMFRequest(char *inRequest);
private:
nsString mBase64Request;
void *mScriptObject;
};
class nsCrypto: public nsIDOMCrypto,
public nsIScriptObjectOwner {
public:
nsCrypto();
virtual ~nsCrypto();
nsresult init();
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void* aScriptObject);
NS_DECL_ISUPPORTS
NS_DECL_IDOMCRYPTO
static nsresult GetScriptObjectFactory(nsIDOMScriptObjectFactory **aResult);
static nsIDOMScriptObjectFactory *gScriptObjectFactory;
static nsIPrincipal* GetScriptPrincipal(JSContext *cx);
static const char *kPSMComponentProgID;
private:
nsIPSMComponent *mPSM;
nsString mVersionString;
PRBool mVersionStringSet;
void *mScriptObject;
};
class nsPkcs11 : public nsIDOMPkcs11,
public nsIScriptObjectOwner {
public:
nsPkcs11();
virtual ~nsPkcs11();
nsresult init();
NS_DECL_ISUPPORTS
NS_DECL_IDOMPKCS11
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void* aScriptObject);
private:
nsIPSMComponent *mPSM;
void *mScriptObject;
};
nsresult
getPSMComponent(nsIPSMComponent ** retPSM);
#endif //_nsCrypto_h_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Terry Hayes <thayes@netscape.com>
* Steve Morse <morse@netscape.com>
*/
#ifndef _NSFSDR_H_
#define _NSFSDR_H_
#include "nsISecretDecoderRing.h"
// ===============================================
// nsFSecretDecoderRing - "fake" implementation of nsISecretDecoderRing
// ===============================================
#define NS_FSDR_CLASSNAME "Fake Secret Decoder Ring"
#define NS_FSDR_CID \
{ 0x1ee28720, 0x2b93, 0x11d4, { 0xa0, 0xa4, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
#define NS_FSDR_PROGID "netscape.security.fsdr"
class nsFSecretDecoderRing : public nsISecretDecoderRing
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISECRETDECODERRING
nsFSecretDecoderRing();
virtual ~nsFSecretDecoderRing();
nsresult init();
private:
nsIPSMComponent *mPSM;
static const char *kPSMComponentProgID;
nsresult encode(const unsigned char *data, PRInt32 dataLen, char **_retval);
nsresult decode(const char *data, unsigned char **result, PRInt32 * _retval);
};
#endif /* _NSFSDR_H_ */

View File

@@ -0,0 +1,255 @@
//For some weird reason, nsProxiedService has to be the first file
//included. Don't ask me, I'm just the messenger.
#include "nsProxiedService.h"
#include "nsKeygenHandler.h"
#include "nsVoidArray.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsIServiceManager.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIContent.h"
#include "nsIPSMComponent.h"
#include "nsIPSMUIHandler.h"
#include "nsPSMUICallbacks.h"
#include "nsCrypto.h"
#include "cmtcmn.h"
#include "cmtjs.h"
//These defines are taken from the PKCS#11 spec
#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
#define CKM_DSA_KEY_PAIR_GEN 0x00000010
static NS_DEFINE_IID(kFormProcessorIID, NS_IFORMPROCESSOR_IID);
static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID);
static const char *mozKeyGen = "-mozilla-keygen";
NS_IMPL_ADDREF(nsKeygenFormProcessor);
NS_IMPL_RELEASE(nsKeygenFormProcessor);
NS_IMPL_QUERY_INTERFACE(nsKeygenFormProcessor, kFormProcessorIID);
nsKeygenFormProcessor::nsKeygenFormProcessor()
{
NS_INIT_REFCNT();
getPSMComponent(&mPSM);
}
char *
nsKeygenFormProcessor::ChooseToken(PCMT_CONTROL control,
CMKeyGenTagArg *psmarg,
CMKeyGenTagReq *reason)
{
CMUint32 resID;
CMTStatus crv;
CMTItem url;
char *keyString = nsnull;
nsresult rv = NS_OK;
NameList *tokenNames;
int i;
// In this case, PSM provided us with a list of potential tokens to choose
// from, but we're gonna make it use it's UI for now, so let's delte the
// memory associated with the structure it sent back.
tokenNames = (NameList*)psmarg->current;
for (i=0; i < tokenNames->numitems; i++) {
nsCRT::free(tokenNames->names[i]);
}
nsCRT::free((char*)tokenNames);
resID = psmarg->rid;
memset(&url, 0, sizeof(CMTItem));
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
crv = CMT_GetStringAttribute(control, resID, SSM_FID_CHOOSE_TOKEN_URL, &url);
if (crv != CMTSuccess) {
goto loser;
}
if (NS_SUCCEEDED(rv)) {
handler->DisplayURI(400, 300, PR_TRUE, (char*)url.data);
} else {
goto loser;
}
return CMT_GetGenKeyResponse(control, psmarg, reason);
loser:
if (keyString)
nsCRT::free(keyString);
return nsnull;
}
char *
nsKeygenFormProcessor::SetUserPassword(PCMT_CONTROL control,
CMKeyGenTagArg *psmarg,
CMKeyGenTagReq *reason)
{
nsresult rv;
CMTStatus crv;
CMTItem url;
char *keystring=nsnull;
// We need to delete the memory the PSM client API allocated for us since
// we're just gonna tell it to use it's own UI.
nsCRT::free((char*)psmarg->current);
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
memset (&url, 0, sizeof(CMTItem));
crv = CMT_GetStringAttribute(control,psmarg->rid, SSM_FID_INIT_DB_URL, &url);
if (crv != CMTSuccess || NS_FAILED(rv)){
goto loser;
}
handler->DisplayURI(500, 450, PR_TRUE, (char*)url.data);
return CMT_GetGenKeyResponse(control, psmarg, reason);
loser:
if (keystring)
nsCRT::free(keystring);
return nsnull;
}
nsresult
nsKeygenFormProcessor::GetPublicKey(nsString& value, nsString& challenge,
nsString& keyType,
nsString& outPublicKey, nsString& pqg)
{
PCMT_CONTROL control;
nsresult rv;
CMKeyGenParams *params = nsnull;
CMKeyGenTagArg *psmarg = nsnull;
CMKeyGenTagReq reason;
char *emptyCString = "null";
char *keystring = nsnull;
rv = mPSM->GetControlConnection(&control);
if (NS_FAILED(rv)) {
goto loser;
}
params = new CMKeyGenParams;
if (params == nsnull) {
goto loser;
}
params->typeString = (keyType.IsEmpty()) ? emptyCString :
keyType.ToNewCString();
params->challenge = (challenge.IsEmpty()) ? emptyCString :
challenge.ToNewCString();
params->choiceString = value.ToNewCString();
params->pqgString = (pqg.IsEmpty()) ? emptyCString : pqg.ToNewCString();
psmarg = new CMKeyGenTagArg;
if (psmarg == nsnull) {
goto loser;
}
// ARGH, while this is going on, we need to lock the control
// connection so that the event loop doesn't drop our response on
// the floor.
CMT_LockConnection(control);
psmarg->op = CM_KEYGEN_START;
psmarg->rid = 0;
psmarg->tokenName = NULL;
psmarg->current = params;
keystring = CMT_GenKeyOldStyle(control, psmarg, &reason);
while (!keystring) {
psmarg->op = reason;
switch (psmarg->op) {
case CM_KEYGEN_PICK_TOKEN:
keystring = ChooseToken(control, psmarg, &reason);
break;
case CM_KEYGEN_SET_PASSWORD:
keystring = SetUserPassword(control, psmarg, &reason);
break;
case CM_KEYGEN_ERR:
default:
goto loser;
}
}
CMT_UnlockConnection(control);
outPublicKey.AssignWithConversion(keystring);
nsCRT::free(keystring);
return NS_OK;
loser:
return NS_ERROR_FAILURE;
}
NS_METHOD
nsKeygenFormProcessor::ProcessValue(nsIDOMHTMLElement *aElement,
const nsString& aName,
nsString& aValue)
{
#ifdef DEBUG_javi
char *name = aName.ToNewCString();
char *value = aValue.ToNewCString();
printf("ProcessValue: name %s value %s\n", name, value);
delete [] name;
delete [] value;
#endif
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMHTMLSelectElement>selectElement;
nsresult res = aElement->QueryInterface(kIDOMHTMLSelectElementIID,
getter_AddRefs(selectElement));
if (NS_SUCCEEDED(res)) {
nsAutoString keygenvalue;
nsAutoString challengeValue;
nsString publicKey;
nsString mozillaKeygen;
nsString mozType;
mozType.AssignWithConversion("_moz-type");
mozillaKeygen.AssignWithConversion(mozKeyGen);
res = selectElement->GetAttribute(mozType, keygenvalue);
if (NS_CONTENT_ATTR_HAS_VALUE == res && keygenvalue.Equals(mozillaKeygen)) {
nsString challenge;
nsString keyType;
nsString keyTypeValue;
nsString pqg, pqgValue;
challenge.AssignWithConversion("challenge");
pqg.AssignWithConversion("pqg");
res = selectElement->GetAttribute(pqg, pqgValue);
keyType.AssignWithConversion("keytype");
res = selectElement->GetAttribute(keyType, keyTypeValue);
if (NS_FAILED(res) || keyTypeValue.IsEmpty()) {
// If this field is not present, we default to rsa.
keyTypeValue.AssignWithConversion("rsa");
}
res = selectElement->GetAttribute(challenge, challengeValue);
rv = GetPublicKey(aValue, challenge, keyTypeValue,
publicKey, pqgValue);
aValue = publicKey;
}
}
return rv;
}
NS_METHOD nsKeygenFormProcessor::ProvideContent(const nsString& aFormType,
nsVoidArray& aContent,
nsString& aAttribute)
{
nsString selectString;
nsresult rv;
PCMT_CONTROL control;
PRUint32 i;
selectString.AssignWithConversion("SELECT");
if (aFormType.EqualsIgnoreCase(selectString)) {
nsString *selectString;
char **result;
rv = mPSM->GetControlConnection(&control);
if (NS_FAILED(rv)) {
goto loser;
}
result = CMT_GetKeyChoiceList(control, "rsa"/*Need to figure out if DSA*/,
nsnull);
for (i=0; result[i] != nsnull; i++) {
selectString = new nsString;
selectString->AssignWithConversion(result[i]);
aContent.AppendElement(selectString);
delete []result[i];
}
delete []result;
aAttribute.AssignWithConversion(mozKeyGen);
}
return NS_OK;
loser:
return NS_ERROR_FAILURE;
}

View File

@@ -0,0 +1,32 @@
#ifndef _NSKEYGENHANDLER_H_
#define _NSKEYGENHANDLER_H_
// Form Processor
#include "nsIFormProcessor.h"
#include "ssmdefs.h"
#include "cmtcmn.h"
class nsIPSMComponent;
class nsKeygenFormProcessor : public nsIFormProcessor {
public:
nsKeygenFormProcessor();
NS_IMETHOD ProcessValue(nsIDOMHTMLElement *aElement,
const nsString& aName,
nsString& aValue);
NS_IMETHOD ProvideContent(const nsString& aFormType,
nsVoidArray& aContent,
nsString& aAttribute);
NS_DECL_ISUPPORTS
protected:
nsresult GetPublicKey(nsString& value, nsString& challenge,
nsString& keyType, nsString& outPublicKey,
nsString& pqg);
char * ChooseToken(PCMT_CONTROL control, CMKeyGenTagArg *psmarg,
CMKeyGenTagReq *reason);
char * SetUserPassword(PCMT_CONTROL control, CMKeyGenTagArg *psmarg,
CMKeyGenTagReq *reason);
nsIPSMComponent *mPSM;
};
#endif //_NSKEYGENHANDLER_H_

View File

@@ -0,0 +1,935 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Mitch Stoltz <mstoltz@netscape.com>
*/
#include "nsProxiedService.h"
#include "nsPSMUICallbacks.h"
#include "VerReg.h"
#include "nspr.h"
#include "nsPSMComponent.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#include "nsIURI.h"
#include "nsIChannel.h"
#include "nsIInputStream.h"
#include "nsIStreamListener.h"
#include "nsIPref.h"
#include "nsIProfile.h"
#include "nsILocalFile.h"
#include "nsDirectoryService.h"
#include "rsrcids.h"
#include "nsPSMMutex.h"
#include "nsPSMShimLayer.h"
#include "nsPSMUICallbacks.h"
#include "nsISecureBrowserUI.h"
#include "nsIDocumentLoaderObserver.h"
#include "nsIScriptSecurityManager.h"
#include "nsICertificatePrincipal.h"
#include "nsIProtocolProxyService.h"
#define PSM_VERSION_REG_KEY "/Netscape/Personal Security Manager"
#ifdef WIN32
#define PSM_FILE_NAME "psm.exe"
#elif XP_UNIX
#define PSM_FILE_NAME "start-psm"
#else
#define PSM_FILE_NAME "psm"
#endif
static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
static NS_DEFINE_CID(kProfileCID, NS_PROFILE_CID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_CID(kProtocolProxyServiceCID, NS_PROTOCOLPROXYSERVICE_CID);
nsPSMComponent* nsPSMComponent::mInstance = nsnull;
nsPSMComponent::nsPSMComponent()
{
NS_INIT_REFCNT();
mControl = nsnull;
}
nsPSMComponent::~nsPSMComponent()
{
if (mControl)
{
CMT_CloseControlConnection(mControl);
mControl = nsnull;
}
}
NS_IMETHODIMP
nsPSMComponent::CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
if (!aResult) {
return NS_ERROR_INVALID_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
if (mInstance == nsnull)
{
mInstance = new nsPSMComponent();
}
if (mInstance == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mInstance->QueryInterface(aIID, aResult);
if (NS_FAILED(rv))
{
*aResult = nsnull;
}
return rv;
}
/* nsISupports Implementation for the class */
NS_IMPL_THREADSAFE_ISUPPORTS3(nsPSMComponent,
nsIPSMComponent,
nsIContentHandler,
nsISignatureVerifier);
#define INIT_NUM_PREFS 100
/* preference types */
#define STRING_PREF 0
#define BOOL_PREF 1
#define INT_PREF 2
/* resizable list struct that contains pref items */
typedef struct CMSetPrefList {
int n; /* number of filled items */
int capacity; /* allocated memory */
CMTSetPrefElement* list; /* actual list */
} CMSetPrefList;
static void get_pack_bool_pref(nsIPref *prefManager, char* key, CMTSetPrefElement* list, int* n)
{
PRBool boolpref;
list[*n].key = nsCRT::strdup(key);
list[*n].type = BOOL_PREF;
if ((prefManager->GetBoolPref(key, &boolpref) != 0) || boolpref)
{
list[*n].value = nsCRT::strdup("true");
}
else
{
list[*n].value = nsCRT::strdup("false");
}
(*n)++; /* increment the counter after done packing */
return;
}
static void SaveAllPrefs(int number, CMTSetPrefElement* list)
{
nsCOMPtr<nsIPref> prefManager;
nsresult res = nsServiceManager::GetService(kPrefCID,
nsIPref::GetIID(),
getter_AddRefs(prefManager));
if (NS_FAILED(res) || !prefManager)
{
return;
}
int i;
int intval;
for (i = 0; i < number; i++)
{
if (list[i].key == nsnull)
{
/* misconfigured item: next */
continue;
}
switch (list[i].type)
{
case 0: /* string type */
prefManager->SetCharPref(list[i].key, list[i].value);
break;
case 1: /* boolean type */
if (strcmp(list[i].value, "true") == 0) {
prefManager->SetBoolPref(list[i].key, (PRBool)1);
}
else if (strcmp(list[i].value, "false") == 0) {
prefManager->SetBoolPref(list[i].key, (PRBool)0);
}
break;
case 2:
intval = atoi(list[i].value);
prefManager->SetIntPref(list[i].key, intval);
break;
default:
break;
}
}
return;
}
NS_IMETHODIMP
nsPSMComponent::PassPrefs()
{
// if we have not passed anything to psm yet, this function can just return.
if (!mControl)
return NS_OK;
int i;
nsresult rv = NS_ERROR_FAILURE;
char* strpref = NULL;
int intpref;
PRBool boolpref;
CMSetPrefList prefs = {0};
CMTSetPrefElement* list = NULL;
char* pickAuto = "Select Automatically";
char* alwaysAsk = "Ask Every Time";
nsCOMPtr<nsIPref> prefManager;
nsresult res = nsServiceManager::GetService(kPrefCID,
nsIPref::GetIID(),
getter_AddRefs(prefManager));
if (NS_OK != res)
{
return NS_ERROR_FAILURE;
}
/* allocate memory for list */
prefs.n = 0; /* counter */
prefs.capacity = INIT_NUM_PREFS;
prefs.list = (CMTSetPrefElement*) new char[(INIT_NUM_PREFS * sizeof(CMTSetPrefElement))];
if (prefs.list == NULL)
{
return rv;
}
/* shorthand */
list = prefs.list;
/* get preferences */
get_pack_bool_pref(prefManager, "security.enable_ssl2", (CMTSetPrefElement*)list, &(prefs.n));
get_pack_bool_pref(prefManager, "security.enable_ssl3", (CMTSetPrefElement*)list, &(prefs.n));
/* this pref is a boolean pref in nature but a string pref for
* historical reason
*/
list[prefs.n].key = nsCRT::strdup("security.default_personal_cert");
list[prefs.n].type = STRING_PREF;
if ((prefManager->CopyCharPref(list[prefs.n].key, &strpref) == 0) && (strcmp(strpref, pickAuto) == 0))
{
list[prefs.n].value = nsCRT::strdup(pickAuto);
}
else
{
/* although one could choose a specific cert for client auth in
* Nova, that mode is deprecated with PSM and mapped to ASK
*/
list[prefs.n].value = nsCRT::strdup(alwaysAsk);
}
prefs.n++;
if (strpref != NULL)
{
nsCRT::free(strpref);
}
list[prefs.n].key = nsCRT::strdup("security.default_mail_cert");
list[prefs.n].type = STRING_PREF;
if (prefManager->CopyCharPref(list[prefs.n].key, &list[prefs.n].value) != 0)
{
list[prefs.n].value = NULL;
}
prefs.n++;
list[prefs.n].key = nsCRT::strdup("security.ask_for_password");
list[prefs.n].type = INT_PREF;
if (prefManager->GetIntPref(list[prefs.n].key, &intpref) != 0)
{
intpref = 0; /* default */
}
list[prefs.n].value = PR_smprintf("%d", intpref);
prefs.n++;
list[prefs.n].key = nsCRT::strdup("security.password_lifetime");
list[prefs.n].type = INT_PREF;
if (prefManager->GetIntPref(list[prefs.n].key, &intpref) != 0)
{
intpref = 30; /* default */
}
list[prefs.n].value = PR_smprintf("%d", intpref);
prefs.n++;
/* OCSP preferences */
/* XXX since these are the new ones added by PSM, we will be more
* error-tolerant in fetching them
*/
if (prefManager->GetBoolPref("security.OCSP.enabled", &boolpref) == 0)
{
if (boolpref)
{
list[prefs.n].value = nsCRT::strdup("true");
}
else
{
list[prefs.n].value = nsCRT::strdup("false");
}
list[prefs.n].key = nsCRT::strdup("security.OCSP.enabled");
list[prefs.n].type = BOOL_PREF;
prefs.n++;
}
if (prefManager->GetBoolPref("security.OCSP.useDefaultResponder", &boolpref) == 0)
{
if (boolpref)
{
list[prefs.n].value = nsCRT::strdup("true");
}
else
{
list[prefs.n].value = nsCRT::strdup("false");
}
list[prefs.n].key = nsCRT::strdup("security.OCSP.useDefaultResponder");
list[prefs.n].type = BOOL_PREF;
prefs.n++;
}
if (prefManager->CopyCharPref("security.OCSP.URL", &strpref) == 0)
{
list[prefs.n].value = strpref;
list[prefs.n].key = nsCRT::strdup("security.OCSP.URL");
list[prefs.n].type = STRING_PREF;
prefs.n++;
}
if (prefManager->CopyCharPref("security.OCSP.signingCA", &strpref) == 0)
{
list[prefs.n].value = strpref;
list[prefs.n].key = nsCRT::strdup("security.OCSP.signingCA");
list[prefs.n].type = STRING_PREF;
prefs.n++;
}
/* now application-specific preferences */
/* get navigator preferences */
get_pack_bool_pref(prefManager, "security.warn_entering_secure", (CMTSetPrefElement*)list, &prefs.n);
get_pack_bool_pref(prefManager, "security.warn_leaving_secure", (CMTSetPrefElement*)list, &prefs.n);
get_pack_bool_pref(prefManager, "security.warn_viewing_mixed", (CMTSetPrefElement*)list, &prefs.n);
get_pack_bool_pref(prefManager, "security.warn_submit_insecure", (CMTSetPrefElement*)list, &prefs.n);
// Add any other prefs here such as ldap or mail/news.
CMT_SetSavePrefsCallback(mControl, (savePrefsCallback_fn)SaveAllPrefs);
if (CMT_PassAllPrefs(mControl, prefs.n, (CMTSetPrefElement*)prefs.list) != CMTSuccess)
{
goto loser;
}
rv = NS_OK; /* success */
loser:
/* clean out memory for prefs */
for (i = 0; i < prefs.n; i++)
{
if (prefs.list[i].key != NULL)
{
nsCRT::free(prefs.list[i].key);
}
if (prefs.list[i].value != NULL)
{
nsCRT::free(prefs.list[i].value);
}
}
if (prefs.list != NULL)
{
delete(prefs.list);
}
return rv;
}
#ifdef XP_MAC
extern "C" {
void RunMacPSM(void* arg);
PRThread* SSM_CreateAndRegisterThread(PRThreadType type, void (*start)(void *arg),
void *arg, PRThreadPriority priority,
PRThreadScope scope, PRThreadState state,
PRUint32 stackSize);
void SSM_KillAllThreads(void);
}
#endif
NS_IMETHODIMP
nsPSMComponent::GetControlConnection( CMT_CONTROL * *_retval )
{
nsresult rv;
*_retval = nsnull;
if (mControl)
{
*_retval = mControl;
return NS_OK;
}
else /* initialize mutex, sock table, etc. */
{
if (nsPSMMutexInit() != PR_SUCCESS)
return NS_ERROR_FAILURE;
#ifdef XP_MAC
/* FIXME: Really need better error handling in PSM, which simply exits on error. */
/* use a cached monitor to rendezvous with the PSM thread. */
PRMonitor* monitor = PR_CEnterMonitor(this);
if (monitor != nsnull) {
/* create the Cartman thread, and let it run awhile to get things going. */
PRThread* cartmanThread = SSM_CreateAndRegisterThread(PR_USER_THREAD, RunMacPSM,
this, PR_PRIORITY_NORMAL,
PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
if (cartmanThread != nsnull) {
/* need a good way to rendezvouz with the Cartman thread. */
PR_CWait(this, PR_INTERVAL_NO_TIMEOUT);
}
PR_CExitMonitor(this);
}
#endif
// Try to see if it is open already
mControl = CMT_ControlConnect(&nsPSMMutexTbl, &nsPSMShimTbl);
// Find the one in the bin directory
if (mControl == nsnull)
{
nsCOMPtr<nsILocalFile> psmAppFile;
NS_WITH_SERVICE(nsIProperties, directoryService, NS_DIRECTORY_SERVICE_PROGID, &rv);
if (NS_FAILED(rv)) return rv;
directoryService->Get("system.OS_CurrentProcessDirectory",
NS_GET_IID(nsIFile),
getter_AddRefs(psmAppFile));
psmAppFile->Append("psm");
psmAppFile->Append(PSM_FILE_NAME);
PRBool isExecutable, exists;
psmAppFile->Exists(&exists);
psmAppFile->IsExecutable(&isExecutable);
if (exists && isExecutable)
{
nsXPIDLCString path;
psmAppFile->GetPath(getter_Copies(path));
// FIX THIS. using a file path is totally wrong here.
mControl = CMT_EstablishControlConnection((char*)(const char*)path, &nsPSMShimTbl, &nsPSMMutexTbl);
}
}
// Get the one in the version registry
if (mControl == nsnull)
{
//Try to find it.
int err;
char filepath[MAXREGPATHLEN];
err = VR_GetPath(PSM_VERSION_REG_KEY, sizeof(filepath), filepath);
if ( err == REGERR_OK )
{
nsFileSpec psmSpec(filepath);
psmSpec += PSM_FILE_NAME;
if (psmSpec.Exists())
{
mControl = CMT_EstablishControlConnection((char *)psmSpec.GetNativePathCString(), &nsPSMShimTbl, &nsPSMMutexTbl);
}
}
}
if (!mControl || InitPSMUICallbacks(mControl) != PR_SUCCESS)
goto failure;
nsFileSpec profileSpec;
PRUnichar* profileName;
NS_WITH_SERVICE(nsIProfile, profile, kProfileCID, &rv);
if (NS_FAILED(rv)) goto failure;
rv = profile->GetCurrentProfileDir(&profileSpec);
if (NS_FAILED(rv)) goto failure;;
#ifdef XP_MAC
profileSpec += "Security";
// make sure the dir exists
profileSpec.CreateDirectory();
#endif
rv = profile->GetCurrentProfile(&profileName);
if (NS_FAILED(rv)) goto failure;
CMTStatus psmStatus;
nsCAutoString profilenameC;
profilenameC.AssignWithConversion(profileName);
psmStatus = CMT_Hello( mControl,
PROTOCOL_VERSION,
profilenameC,
(char*)profileSpec.GetNativePathCString());
if (psmStatus == CMTFailure)
{
PR_FREEIF(profileName);
goto failure;
}
if (InitPSMEventLoop(mControl) != PR_SUCCESS)
{
PR_FREEIF(profileName);
goto failure;
}
if (NS_FAILED(PassPrefs()))
{
PR_FREEIF(profileName);
goto failure;
}
PR_FREEIF(profileName);
nsCOMPtr<nsIProtocolProxyService> proxySvc = do_GetService(kProtocolProxyServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
proxySvc->AddNoProxyFor("127.0.0.1", mControl->port);
*_retval = mControl;
return NS_OK;
}
failure:
#ifdef DEBUG
printf("*** Failure setting up Cartman! \n");
#endif
if (mControl)
{
CMT_CloseControlConnection(mControl);
mControl = NULL;
}
// TODO we need to unregister our UI callback BEFORE destroying our mutex.
// nsPSMMutexDestroy();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPSMComponent::DisplaySecurityAdvisor(const char *pickledStatus, const char *hostName)
{
CMT_CONTROL *controlConnection;
GetControlConnection( &controlConnection );
if (DisplayPSMUIDialog(controlConnection, pickledStatus, hostName) == PR_SUCCESS)
return NS_OK;
return NS_ERROR_FAILURE;
}
class CertDownloader : public nsIStreamListener
{
public:
CertDownloader() {NS_ASSERTION(0, "don't use this constructor."); }
CertDownloader(PRInt32 type);
virtual ~CertDownloader();
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
protected:
char* mByteData;
PRInt32 mBufferOffset;
PRInt32 mContentLength;
PRInt32 mType;
};
CertDownloader::CertDownloader(PRInt32 type)
{
NS_INIT_REFCNT();
mByteData = nsnull;
mType = type;
}
CertDownloader::~CertDownloader()
{
if (mByteData)
nsMemory::Free(mByteData);
}
NS_IMPL_ISUPPORTS(CertDownloader,NS_GET_IID(nsIStreamListener));
NS_IMETHODIMP
CertDownloader::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
channel->GetContentLength(&mContentLength);
if (mContentLength == -1)
return NS_ERROR_FAILURE;
mBufferOffset = 0;
mByteData = (char*) nsMemory::Alloc(mContentLength);
if (!mByteData)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
CertDownloader::OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
if (!mByteData)
return NS_ERROR_OUT_OF_MEMORY;
PRUint32 amt;
nsresult err;
do
{
err = aIStream->Read(mByteData+mBufferOffset, mContentLength-mBufferOffset, &amt);
if (amt == 0) break;
if (NS_FAILED(err)) return err;
aLength -= amt;
mBufferOffset += amt;
} while (aLength > 0);
return NS_OK;
}
NS_IMETHODIMP
CertDownloader::OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg)
{
nsCOMPtr<nsIPSMComponent> psm = do_QueryInterface(context);
if (!psm) return NS_ERROR_FAILURE;
CMT_CONTROL *controlConnection;
psm->GetControlConnection( &controlConnection );
unsigned int certID;
certID = CMT_DecodeAndCreateTempCert(controlConnection, mByteData, mContentLength, mType);
if (certID)
CMT_DestroyResource(controlConnection, certID, SSM_RESTYPE_CERTIFICATE);
return NS_OK;
}
/* other mime types that we should handle sometime:
application/x-pkcs7-crl
application/x-pkcs7-mime
application/pkcs7-signature
application/pre-encrypted
*/
NS_IMETHODIMP
nsPSMComponent::HandleContent(const char * aContentType,
const char * aCommand,
const char * aWindowTarget,
nsISupports* aWindowContext,
nsIChannel * aChannel)
{
// We were called via CI. We better protect ourselves and addref.
NS_ADDREF_THIS();
nsresult rv = NS_OK;
if (!aChannel) return NS_ERROR_NULL_POINTER;
CMUint32 type = -1;
if ( nsCRT::strcasecmp(aContentType, "application/x-x509-ca-cert") == 0)
{
type = 1; //CA cert
}
else if (nsCRT::strcasecmp(aContentType, "application/x-x509-server-cert") == 0)
{
type = 2; //Server cert
}
else if (nsCRT::strcasecmp(aContentType, "application/x-x509-user-cert") == 0)
{
type = 3; //User cert
}
else if (nsCRT::strcasecmp(aContentType, "application/x-x509-email-cert") == 0)
{
type = 4; //Someone else's email cert
}
if (type != -1)
{
// I can't directly open the passed channel cause it fails :-(
nsCOMPtr<nsIURI> uri;
rv = aChannel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIChannel> channel;
rv = NS_OpenURI(getter_AddRefs(channel), uri);
if (NS_FAILED(rv)) return rv;
return channel->AsyncRead(new CertDownloader(type), NS_STATIC_CAST(nsIPSMComponent*,this));
}
return NS_ERROR_NOT_IMPLEMENTED;
}
//---------------------------------------------
// Functions Implenenting NSISignatureVerifier
//---------------------------------------------
NS_IMETHODIMP
nsPSMComponent::HashBegin(PRUint32 alg, PRUint32* id)
{
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
if(CMT_HashCreate(controlConnection, alg, (CMUint32*)id) != CMTSuccess)
return NS_ERROR_FAILURE;
if(CMT_HASH_Begin(controlConnection, *id) != CMTSuccess)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsPSMComponent::HashUpdate(PRUint32 id, const char* buf, PRUint32 buflen)
{
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
if (CMT_HASH_Update(controlConnection, id,
(const unsigned char*)buf, buflen) != CMTSuccess)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsPSMComponent::HashEnd(PRUint32 id, unsigned char** hash,
PRUint32* hashLen, PRUint32 maxLen)
{
if (!hash)
return NS_ERROR_ILLEGAL_VALUE;
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
if(CMT_HASH_End(controlConnection, id, *hash,
(CMUint32*)hashLen, maxLen) != CMTSuccess)
return NS_ERROR_FAILURE;
CMT_HASH_Destroy(controlConnection, id);
return NS_OK;
}
NS_IMETHODIMP
nsPSMComponent::CreatePrincipalFromSignature(const char* aRSABuf, PRUint32 aRSABufLen,
nsIPrincipal** aPrincipal)
{
PRInt32 errorCode;
return VerifySignature(aRSABuf, aRSABufLen, nsnull, 0, &errorCode, aPrincipal);
}
PR_STATIC_CALLBACK(void)
UselessPK7DataSink(void* arg, const char* buf, CMUint32 len)
{
}
NS_IMETHODIMP
nsPSMComponent::VerifySignature(const char* aRSABuf, PRUint32 aRSABufLen,
const char* aPlaintext, PRUint32 aPlaintextLen,
PRInt32* aErrorCode,
nsIPrincipal** aPrincipal)
{
if (!aPrincipal || !aErrorCode)
return NS_ERROR_NULL_POINTER;
*aErrorCode = 0;
*aPrincipal = nsnull;
CMT_CONTROL *controlConnection;
if (NS_FAILED(GetControlConnection( &controlConnection )))
return NS_ERROR_FAILURE;
//-- Decode the signature stream
CMUint32 decoderID;
CMInt32* blah = nsnull;
CMTStatus result = CMT_PKCS7DecoderStart(controlConnection, nsnull,
&decoderID, blah,
UselessPK7DataSink, nsnull);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
result = CMT_PKCS7DecoderUpdate(controlConnection, decoderID, aRSABuf, aRSABufLen);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
CMUint32 contentInfo;
result = CMT_PKCS7DecoderFinish(controlConnection,
decoderID, &contentInfo);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
CMTItem hashItem;
hashItem.data = 0;
hashItem.len = 0;
//-- If a plaintext was provided, hash it.
if (aPlaintext)
{
CMUint32 hashId;
CMT_HashCreate(controlConnection, nsISignatureVerifier::SHA1, &hashId);
CMT_HASH_Begin(controlConnection, hashId);
CMTStatus result = CMT_HASH_Update(controlConnection, hashId,
(const unsigned char*)aPlaintext, aPlaintextLen);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
unsigned char* hash = (unsigned char*)PR_MALLOC(nsISignatureVerifier::SHA1_LENGTH);
if (!hash) return NS_ERROR_OUT_OF_MEMORY;
CMUint32 hashLen;
result = CMT_HASH_End(controlConnection, hashId, hash,
&hashLen, nsISignatureVerifier::SHA1_LENGTH);
if (result != CMTSuccess)
{
PR_FREEIF(hash);
return NS_ERROR_FAILURE;
}
NS_ASSERTION(hashLen == nsISignatureVerifier::SHA1_LENGTH,
"PSMComponent: Hash too short.");
CMT_HASH_Destroy(controlConnection, hashId);
hashItem.data = hash;
hashItem.len = hashLen;
}
//-- Verify signature
// We need to call this function even if we're only creating a principal, not
// verifying, because PSM won't give us certificate information unless this
// function has been called.
result = CMT_PKCS7VerifyDetachedSignature(controlConnection, contentInfo,
6 /* =Object Signing Cert */,
3 /* =SHA1 algorithm (MD5=2)*/,
1,/* Save Certificate */
&hashItem, (CMInt32*)aErrorCode);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
if (aPlaintext && *aErrorCode != 0) return NS_OK; // Verification failed.
CMUint32 certID;
result = CMT_GetRIDAttribute(controlConnection, contentInfo,
SSM_FID_P7CINFO_SIGNER_CERT, &certID);
if ((result != CMTSuccess) || !certID) return NS_OK; // No signature present
CMTItem fingerprint;
result = CMT_GetStringAttribute(controlConnection, certID,
SSM_FID_CERT_FINGERPRINT, &fingerprint);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
//-- Get a principal
nsresult rv;
NS_WITH_SERVICE(nsIScriptSecurityManager, secMan,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv)
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = secMan->GetCertificatePrincipal((char*)fingerprint.data,
aPrincipal);
if (NS_FAILED(rv)) return rv;
//-- Get common name and store it in the principal.
// Using common name + organizational unit as the user-visible certificate name
nsCOMPtr<nsICertificatePrincipal> certificate = do_QueryInterface(*aPrincipal, &rv);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
CMTItem common;
result = CMT_GetStringAttribute(controlConnection, certID,
SSM_FID_CERT_COMMON_NAME, &common);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
CMTItem subject;
result = CMT_GetStringAttribute(controlConnection, certID,
SSM_FID_CERT_SUBJECT_NAME, &subject);
if (result != CMTSuccess) return NS_ERROR_FAILURE;
nsCAutoString commonName;
commonName = (char*)common.data;
static const char orgUnitTag[] = " OU=";
char* orgUnitPos = PL_strstr((char*)subject.data, orgUnitTag);
if (orgUnitPos)
{
orgUnitPos += sizeof(orgUnitTag)-1;
char* orgUnitEnd = PL_strchr(orgUnitPos, ',');
PRInt32 orgUnitLen;
if(orgUnitEnd)
orgUnitLen = orgUnitEnd - orgUnitPos;
else
orgUnitLen = PL_strlen(orgUnitPos);
commonName.Append(' ');
commonName.Append(orgUnitPos, orgUnitLen);
}
char* commonChar = commonName.ToNewCString();
if (!commonChar) return NS_ERROR_OUT_OF_MEMORY;
rv = certificate->SetCommonName(commonChar);
Recycle(commonChar);
return rv;
}

View File

@@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nscore.h"
#include "nsIPSMComponent.h"
#include "nsISignatureVerifier.h"
#include "nsIStringBundle.h"
#include "nsIContentHandler.h"
#define SECURITY_STRING_BUNDLE_URL "chrome://communicator/locale/security.properties"
#define NS_PSMCOMPONENT_CID {0xddcae170, 0x5412, 0x11d3, {0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37}}
// Implementation of the PSM component interface.
class nsPSMComponent : public nsIPSMComponent,
public nsIContentHandler,
public nsISignatureVerifier
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR( NS_PSMCOMPONENT_CID );
nsPSMComponent();
virtual ~nsPSMComponent();
NS_DECL_ISUPPORTS
NS_DECL_NSIPSMCOMPONENT
NS_DECL_NSICONTENTHANDLER
NS_DECL_NSISIGNATUREVERIFIER
static NS_METHOD CreatePSMComponent(nsISupports* aOuter, REFNSIID aIID, void **aResult);
private:
PCMT_CONTROL mControl;
nsCOMPtr<nsISupports> mSecureBrowserIU;
static nsPSMComponent* mInstance;
};

View File

@@ -0,0 +1,178 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsIModule.h"
#include "nsIGenericFactory.h"
#include "nsPSMUICallbacks.h"
#include "nsPSMComponent.h"
#include "nsISecureBrowserUI.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsSSLSocketProvider.h"
#include "nsSDR.h"
#include "nsFSDR.h"
#include "nsCrypto.h"
#include "nsKeygenHandler.h"
//For the NS_CRYPTO_PROGID define
#include "nsDOMCID.h"
#include "nsCURILoader.h"
#include "nsISupportsUtils.h"
// Define SDR object constructor
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kFormProcessorCID, NS_IFORMPROCESSOR_CID);
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSecretDecoderRing, init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFSecretDecoderRing, init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCrypto, init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPkcs11, init)
static nsModuleComponentInfo components[] =
{
{
PSM_COMPONENT_CLASSNAME,
NS_PSMCOMPONENT_CID,
PSM_COMPONENT_PROGID,
nsPSMComponent::CreatePSMComponent
},
{
"PSM Content Handler - application/x-x509-ca-cert",
NS_PSMCOMPONENT_CID,
NS_CONTENT_HANDLER_PROGID_PREFIX"application/x-x509-ca-cert",
nsPSMComponent::CreatePSMComponent
},
{
"PSM Content Handler - application/x-x509-server-cert",
NS_PSMCOMPONENT_CID,
NS_CONTENT_HANDLER_PROGID_PREFIX"application/x-x509-server-cert",
nsPSMComponent::CreatePSMComponent
},
{
"PSM Content Handler - application/x-x509-user-cert",
NS_PSMCOMPONENT_CID,
NS_CONTENT_HANDLER_PROGID_PREFIX"application/x-x509-user-cert",
nsPSMComponent::CreatePSMComponent
},
{
"PSM Content Handler - application/x-x509-email-cert",
NS_PSMCOMPONENT_CID,
NS_CONTENT_HANDLER_PROGID_PREFIX"application/x-x509-email-cert",
nsPSMComponent::CreatePSMComponent
},
{
PSM_UI_HANLDER_CLASSNAME,
NS_PSMUIHANDLER_CID,
PSM_UI_HANLDER_PROGID,
nsPSMUIHandlerImpl::CreatePSMUIHandler
},
{
NS_SECURE_BROWSER_UI_CLASSNAME,
NS_SECURE_BROWSER_UI_CID,
NS_SECURE_BROWSER_UI_PROGID,
nsSecureBrowserUIImpl::Create
},
{
NS_SECURE_BROWSER_DOCOBSERVER_CLASSNAME,
NS_SECURE_BROWSER_DOCOBSERVER_CID,
NS_SECURE_BROWSER_DOCOBSERVER_PROGID,
nsSecureBrowserUIImpl::Create
},
{
NS_ISSLSOCKETPROVIDER_CLASSNAME,
NS_SSLSOCKETPROVIDER_CID,
NS_ISSLSOCKETPROVIDER_PROGID,
nsSSLSocketProvider::Create
},
{
NS_SDR_CLASSNAME,
NS_SDR_CID,
NS_SDR_PROGID,
nsSecretDecoderRingConstructor
},
{
NS_FSDR_CLASSNAME,
NS_FSDR_CID,
NS_FSDR_PROGID,
nsFSecretDecoderRingConstructor
},
{
NS_CRYPTO_CLASSNAME,
NS_CRYPTO_CID,
NS_CRYPTO_PROGID,
nsCryptoConstructor
},
{
NS_PKCS11_CLASSNAME,
NS_PKCS11_CID,
NS_PKCS11_PROGID,
nsPkcs11Constructor
}
};
#if 0
NS_IMPL_NSGETMODULE("PSMComponent", components);
#endif
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
nsIFile* location,
nsIModule** result)
{
nsresult rv;
// Put in code to register KEYGEN form input handler.
rv= NS_NewGenericModule("PSMComponent",
sizeof(components) / sizeof(components[0]),
components, nsnull, result);
// Register a form processor. The form processor has the opportunity to
// modify the value's passed during form submission.
nsKeygenFormProcessor* testFormProcessor = new nsKeygenFormProcessor();
nsCOMPtr<nsISupports> formProcessor;
rv = testFormProcessor->QueryInterface(kISupportsIID,
getter_AddRefs(formProcessor));
if (NS_SUCCEEDED(rv) && formProcessor) {
rv = nsServiceManager::RegisterService(kFormProcessorCID, formProcessor);
}
return rv;
}

View File

@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "prmon.h"
#include "prtypes.h"
#include "nsPSMMutex.h"
static PRMonitor *_nsPSMMutexVar;
PRStatus
nsPSMMutexInit()
{
if (!_nsPSMMutexVar)
_nsPSMMutexVar = PR_NewMonitor();
return _nsPSMMutexVar ? PR_SUCCESS : PR_FAILURE;
}
PRStatus
nsPSMMutexDestroy()
{
if (!_nsPSMMutexVar)
return PR_FAILURE;
PR_Wait(_nsPSMMutexVar, PR_INTERVAL_NO_TIMEOUT);
PR_DestroyMonitor(_nsPSMMutexVar);
return PR_SUCCESS;
}
static void
nsPSMMutexLock(CMTMutexPointer *p)
{
PR_EnterMonitor(*(PRMonitor **)p);
return;
}
static void
nsPSMMutexUnlock(CMTMutexPointer *p)
{
PR_ExitMonitor(*(PRMonitor **)p);
return;
}
CMT_MUTEX nsPSMMutexTbl =
{
&_nsPSMMutexVar,
(CMTMutexFunction)nsPSMMutexLock,
(CMTMutexFunction)nsPSMMutexUnlock
};

View File

@@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef _NSPSMMUTEX_H
#define _NSPSMMUTEX_H
#include "cmtcmn.h"
PR_BEGIN_EXTERN_C
PR_EXTERN(CMT_MUTEX) nsPSMMutexTbl;
PR_EXTERN(PRStatus) nsPSMMutexInit(void);
PR_EXTERN(PRStatus) nsPSMMutexDestroy(void);
PR_END_EXTERN_C
#endif

View File

@@ -0,0 +1,293 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nspr.h"
#include "nsPSMShimLayer.h"
#ifdef XP_UNIX
#include <sys/stat.h>
#include <unistd.h>
#include "private/pprio.h" /* for PR_Socket */
#endif
#define PSM_TIMEOUT_IN_SEC 300
#define NSPSMSHIMMAXFD 50
static PRIntervalTime gTimeout = PR_INTERVAL_NO_TIMEOUT;
CMT_SocketFuncs nsPSMShimTbl =
{
nsPSMShimGetSocket,
nsPSMShimConnect,
nsPSMShimVerifyUnixSocket,
nsPSMShimSend,
nsPSMShimSelect,
nsPSMShimReceive,
nsPSMShimShutdown,
nsPSMShimClose
};
CMTSocket
nsPSMShimGetSocket(int unixSock)
{
PRStatus rv;
PRFileDesc *fd;
CMSocket *sock;
PRSocketOptionData sockopt;
/*
if (PR_INTERVAL_NO_WAIT == gTimeout)
{
gTimeout = PR_SecondsToInterval(PSM_TIMEOUT_IN_SEC);
}
*/
if (unixSock)
{
#ifndef XP_UNIX
return NULL;
#else
fd = PR_Socket(PR_AF_LOCAL, PR_SOCK_STREAM, 0);
PR_ASSERT(fd);
#endif
}
else
{
fd = PR_NewTCPSocket();
PR_ASSERT(fd);
/* disable Nagle algorithm delay for control sockets */
sockopt.option = PR_SockOpt_NoDelay;
sockopt.value.no_delay = PR_TRUE;
rv = PR_SetSocketOption(fd, &sockopt);
PR_ASSERT(PR_SUCCESS == rv);
}
sock = (CMSocket *)PR_Malloc(sizeof(CMSocket));
if (sock == NULL)
return sock;
sock->fd = fd;
sock->isUnix = unixSock;
memset(&sock->netAddr, 0, sizeof(PRNetAddr));
return (CMTSocket)sock;
}
CMTStatus
nsPSMShimConnect(CMTSocket sock, short port, char *path)
{
CMTStatus rv = CMTSuccess;
PRStatus err;
PRErrorCode errcode;
PRSocketOptionData sockopt;
PRBool nonBlocking;
CMSocket *cmSock = (CMSocket *)sock;
if (!sock) return CMTFailure;
if (cmSock->isUnix)
{
#ifndef XP_UNIX
return CMTFailure;
#else
int pathLen;
if (!path)
{
return CMTFailure;
}
/* check buffer overrun */
pathLen = strlen(path)+1;
pathLen = pathLen < sizeof(cmSock->netAddr.local.path)
? pathLen : sizeof(cmSock->netAddr.local.path);
memcpy(&cmSock->netAddr.local.path, path, pathLen);
cmSock->netAddr.local.family = PR_AF_LOCAL;
#endif
}
else /* cmSock->isUnix */
{
cmSock->netAddr.inet.family = PR_AF_INET;
cmSock->netAddr.inet.port = PR_htons(port);
cmSock->netAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
}
/* Save non-blocking status */
sockopt.option = PR_SockOpt_Nonblocking;
err = PR_GetSocketOption(cmSock->fd, &sockopt);
PR_ASSERT(PR_SUCCESS == err);
nonBlocking = sockopt.value.non_blocking;
/* make connect blocking for now */
sockopt.option = PR_SockOpt_Nonblocking;
sockopt.value.non_blocking = PR_FALSE;
err = PR_SetSocketOption(cmSock->fd, &sockopt);
PR_ASSERT(PR_SUCCESS == err);
err = PR_Connect( cmSock->fd, &cmSock->netAddr, PR_INTERVAL_MAX );
if (err == PR_FAILURE)
{
errcode = PR_GetError();
if (PR_IS_CONNECTED_ERROR != errcode)
rv = CMTFailure;
}
/* restore nonblock status */
if (nonBlocking) {
sockopt.option = PR_SockOpt_Nonblocking;
sockopt.value.non_blocking = nonBlocking;
err = PR_SetSocketOption(cmSock->fd, &sockopt);
PR_ASSERT(PR_SUCCESS == err);
}
return rv;
}
CMTStatus
nsPSMShimVerifyUnixSocket(CMTSocket sock)
{
#ifndef XP_UNIX
return CMTFailure;
#else
int rv;
CMSocket *cmSock;
struct stat statbuf;
cmSock = (CMSocket *)sock;
if (!cmSock || !cmSock->isUnix)
return CMTFailure;
rv = stat(cmSock->netAddr.local.path, &statbuf);
if (rv < 0 || statbuf.st_uid != geteuid() )
{
PR_Close(cmSock->fd);
cmSock->fd = NULL;
PR_Free(cmSock);
return CMTFailure;
}
return CMTSuccess;
#endif
}
size_t
nsPSMShimSend(CMTSocket sock, void *buffer, size_t length)
{
CMSocket *cmSock = (CMSocket *)sock;
if (!sock) return CMTFailure;
return PR_Send(cmSock->fd, buffer, length, 0, gTimeout);
}
size_t
nsPSMShimReceive(CMTSocket sock, void *buffer, size_t bufSize)
{
CMSocket *cmSock = (CMSocket *)sock;
if (!sock) return CMTFailure;
return PR_Recv(cmSock->fd, buffer, bufSize, 0, gTimeout);
}
CMTSocket
nsPSMShimSelect(CMTSocket *socks, int numsocks, int poll)
{
CMSocket **sockArr = (CMSocket **)socks;
PRPollDesc readPDs[NSPSMSHIMMAXFD];
PRIntervalTime timeout;
PRInt32 cnt;
int i;
if (!socks) return NULL;
memset(readPDs, 0, sizeof(readPDs));
PR_ASSERT(NSPSMSHIMMAXFD >= numsocks);
for (i=0; i<numsocks; i++)
{
readPDs[i].fd = sockArr[i]->fd;
readPDs[i].in_flags = PR_POLL_READ;
}
timeout = poll ? PR_INTERVAL_NO_WAIT : PR_INTERVAL_NO_TIMEOUT;
cnt = PR_Poll(readPDs, numsocks, timeout);
/* Figure out which socket was selected */
if (cnt > 0)
{
for (i=0; i<numsocks; i++)
{
if (readPDs[i].out_flags & PR_POLL_READ)
{
return (CMTSocket)sockArr[i];
}
}
}
return NULL;
}
CMTStatus
nsPSMShimShutdown(CMTSocket sock)
{
CMSocket *cmSock = (CMSocket*)sock;
PRStatus rv;
if (!sock) return CMTFailure;
rv = PR_Shutdown(cmSock->fd, PR_SHUTDOWN_SEND);
return (PR_SUCCESS == rv) ? CMTSuccess : CMTFailure;
}
CMTStatus
nsPSMShimClose(CMTSocket sock)
{
CMSocket *cmSock = (CMSocket*)sock;
PRStatus rv = PR_SUCCESS;
PR_ASSERT(cmSock);
if (!sock) return CMTFailure;
rv = PR_Close(cmSock->fd);
cmSock->fd = NULL;
PR_Free(cmSock);
return (PR_SUCCESS == rv) ? CMTSuccess : CMTFailure;
}

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef _NSPSMSHIMLAYER_H_
#define _NSPSMSHIMLAYER_H_
#include "cmtcmn.h"
#include "prio.h"
PR_BEGIN_EXTERN_C
typedef struct CMSocket {
PRFileDesc *fd;
PRBool isUnix;
PRNetAddr netAddr;
} CMSocket;
PR_EXTERN(CMT_SocketFuncs) nsPSMShimTbl;
PR_EXTERN(CMTSocket)
nsPSMShimGetSocket(int unixSock);
PR_EXTERN(CMTStatus)
nsPSMShimConnect(CMTSocket sock, short port, char *path);
PR_EXTERN(CMTStatus)
nsPSMShimVerifyUnixSocket(CMTSocket sock);
PR_EXTERN(size_t)
nsPSMShimSend(CMTSocket sock, void *buffer, size_t length);
PR_EXTERN(CMTSocket)
nsPSMShimSelect(CMTSocket *socks, int numsocks, int poll);
PR_EXTERN(size_t)
nsPSMShimReceive(CMTSocket sock, void *buffer, size_t bufSize);
PR_EXTERN(CMTStatus)
nsPSMShimShutdown(CMTSocket sock);
PR_EXTERN(CMTStatus)
nsPSMShimClose(CMTSocket sock);
PR_END_EXTERN_C
#endif /* _NSPSMSHIMLAYER_H_ */

View File

@@ -0,0 +1,348 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#include "nsProxiedService.h"
#include "nsIEventQueueService.h"
#include "nsPSMUICallbacks.h"
#include "nsINetSupportDialogService.h"
#include "nsIFilePicker.h"
#include "nsAppShellCIDs.h"
#include "prprf.h"
#include "prmem.h"
#include "nsSSLIOLayer.h" // for SSMSTRING_PADDED_LENGTH
#include "ssmdefs.h"
#include "rsrcids.h"
// Interfaces Needed
#include "nsIAppShellService.h"
#include "nsIDocShell.h"
#include "nsIDOMWindow.h"
#include "nsIInterfaceRequestor.h"
#include "nsIPrompt.h"
#include "nsIScriptGlobalObject.h"
#include "nsIURL.h"
#include "nsIXULWindow.h"
static NS_DEFINE_IID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID);
static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
// Happy callbacks
static char * PromptUserCallback(void *arg, char *prompt, int isPasswd);
static char * FilePathPromptCallback(void *arg, char *prompt, char *fileRegEx, CMUint32 shouldFileExist);
static void ApplicationFreeCallback(char *userInput);
static void * CartmanUIHandler(uint32 resourceID, void* clientContext, uint32 width, uint32 height,
CMBool isModal, char* urlStr, void *data);
extern "C" void CARTMAN_UIEventLoop(void *data);
/* nsISupports Implementation for the class */
NS_IMPL_THREADSAFE_ISUPPORTS1(nsPSMUIHandlerImpl, nsIPSMUIHandler)
NS_METHOD
nsPSMUIHandlerImpl::DisplayURI(PRInt32 width, PRInt32 height, PRBool modal, const char *urlStr)
{
nsresult rv;
nsCOMPtr<nsIDOMWindow> hiddenWindow;
JSContext *jsContext;
NS_WITH_SERVICE(nsIAppShellService, appShell, kAppShellServiceCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = appShell->GetHiddenWindowAndJSContext( getter_AddRefs( hiddenWindow ),
&jsContext );
if ( NS_SUCCEEDED( rv ) )
{
// Set up arguments for "window.open"
void *stackPtr;
char params[36];
if (modal) // if you change this, remember to change the buffer size above.
strcpy(params, "menubar=no,height=%d,width=%d,modal");
else
strcpy(params, "menubar=no,height=%d,width=%d");
char buffer[256];
PR_snprintf(buffer,
sizeof(buffer),
params,
height,
width );
jsval *argv = JS_PushArguments(jsContext, &stackPtr, "sss", urlStr, "_blank", buffer);
if (argv)
{
// open the window
nsIDOMWindow *newWindow;
hiddenWindow->Open(jsContext, argv, 3, &newWindow);
newWindow->ResizeTo(width, height);
JS_PopArguments(jsContext, stackPtr);
}
}
}
return rv;
}
NS_IMETHODIMP
nsPSMUIHandlerImpl::PromptForFile(const PRUnichar *prompt, const char *fileRegEx, PRBool shouldFileExist, char **outFile)
{
NS_ENSURE_ARG_POINTER(outFile);
nsCOMPtr<nsIFilePicker> fp = do_CreateInstance("component://mozilla/filepicker");
if (!fp)
return NS_ERROR_NULL_POINTER;
fp->Init(nsnull, prompt, nsIFilePicker::modeOpen);
fp->AppendFilter(NS_ConvertASCIItoUCS2(fileRegEx).GetUnicode(), NS_ConvertASCIItoUCS2(fileRegEx).GetUnicode());
fp->AppendFilters(nsIFilePicker::filterAll);
PRInt16 mode;
nsresult rv = fp->Show(&mode);
if (NS_FAILED(rv) || (mode == nsIFilePicker::returnCancel))
return rv;
nsCOMPtr<nsILocalFile> file;
rv = fp->GetFile(getter_AddRefs(file));
if (file)
file->GetPath(outFile);
return rv;
}
NS_METHOD
nsPSMUIHandlerImpl::CreatePSMUIHandler(nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv = NS_OK;
if ( aResult )
{
/* Allocate new find component object. */
nsPSMUIHandlerImpl *component = new nsPSMUIHandlerImpl();
if ( component )
{
/* Allocated OK, do query interface to get proper */
/* pointer and increment refcount. */
rv = component->QueryInterface( aIID, aResult );
if ( NS_FAILED( rv ) )
{
/* refcount still at zero, delete it here. */
delete component;
}
}
else
{
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
else
{
rv = NS_ERROR_NULL_POINTER;
}
return rv;
}
extern "C" void CARTMAN_UIEventLoop(void *data)
{
CMT_EventLoop((PCMT_CONTROL)data);
}
PRStatus InitPSMEventLoop(PCMT_CONTROL control)
{
PR_CreateThread(PR_USER_THREAD,
CARTMAN_UIEventLoop,
control,
PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
0);
return PR_SUCCESS;
}
PRStatus InitPSMUICallbacks(PCMT_CONTROL control)
{
if (!control)
return PR_FAILURE;
CMT_SetPromptCallback(control, (promptCallback_fn)PromptUserCallback, nsnull);
CMT_SetAppFreeCallback(control, (applicationFreeCallback_fn) ApplicationFreeCallback);
CMT_SetFilePathPromptCallback(control, (filePathPromptCallback_fn) FilePathPromptCallback, nsnull);
if (CMT_SetUIHandlerCallback(control, (uiHandlerCallback_fn) CartmanUIHandler, NULL) != CMTSuccess)
return PR_FAILURE;
return PR_SUCCESS;
}
PRStatus DisplayPSMUIDialog(PCMT_CONTROL control, const char *pickledStatus, const char *hostName)
{
CMUint32 advRID = 0;
CMInt32 width = 0;
CMInt32 height = 0;
CMTItem urlItem = {0, NULL, 0};
CMTStatus rv = CMTSuccess;
CMTItem advisorContext = {0, NULL, 0};
void * pwin;
CMTSecurityAdvisorData data;
memset(&data, '\0', sizeof(CMTSecurityAdvisorData));
if (hostName)
{
// if there is a hostName, than this request is about
// a webpage.
data.hostname = (char*) hostName;
data.infoContext = SSM_BROWSER;
if (pickledStatus)
{
CMTItem pickledResource = {0, NULL, 0};
CMUint32 socketStatus = 0;
pickledResource.len = *(int*)(pickledStatus);
pickledResource.data = (unsigned char*) PR_Malloc(SSMSTRING_PADDED_LENGTH(pickledResource.len));
if (! pickledResource.data) return PR_FAILURE;
memcpy(pickledResource.data, pickledStatus+sizeof(int), pickledResource.len);
/* Unpickle the SSL Socket Status */
if (CMT_UnpickleResource( control,
SSM_RESTYPE_SSL_SOCKET_STATUS,
pickledResource,
&socketStatus) == CMTSuccess)
{
data.infoContext = SSM_BROWSER;
data.resID = socketStatus;
}
PR_FREEIF(pickledResource.data);
}
}
/* Create a Security Advisor context object. */
rv = CMT_SecurityAdvisor(control, &data, &advRID);
if (rv != CMTSuccess)
return PR_FAILURE;
/* Get the URL, width, height, etc. from the advisor context. */
rv = CMT_GetStringAttribute(control,
advRID,
SSM_FID_SECADVISOR_URL,
&urlItem);
if ((rv != CMTSuccess) || (!urlItem.data))
return PR_FAILURE;
rv = CMT_GetNumericAttribute(control,
advRID,
SSM_FID_SECADVISOR_WIDTH,
&width);
if (rv != CMTSuccess)
return PR_FAILURE;
rv = CMT_GetNumericAttribute(control,
advRID,
SSM_FID_SECADVISOR_HEIGHT,
&height);
if (rv != CMTSuccess)
return PR_FAILURE;
/* Fire the URL up in a window of its own. */
pwin = CartmanUIHandler(advRID, nsnull, width, height, CM_FALSE, (char*)urlItem.data, NULL);
//allocated by cmt, we can free with free:
free(urlItem.data);
return PR_SUCCESS;
}
void* CartmanUIHandler(uint32 resourceID, void* clientContext, uint32 width, uint32 height, CMBool isModal, char* urlStr, void *data)
{
nsresult rv = NS_OK;
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
if(NS_SUCCEEDED(rv))
handler->DisplayURI(width, height, isModal, urlStr);
return nsnull;
}
char * PromptUserCallback(void *arg, char *prompt, int isPasswd)
{
nsresult rv = NS_OK;
PRUnichar *password;
PRBool value;
NS_WITH_PROXIED_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, NS_UI_THREAD_EVENTQ, &rv);
if (NS_SUCCEEDED(rv)) {
rv = dialog->PromptPassword(nsnull, NS_ConvertASCIItoUCS2(prompt).GetUnicode(),
NS_ConvertASCIItoUCS2(" ").GetUnicode(), // hostname
PR_TRUE, &password, &value);
if (NS_SUCCEEDED(rv) && value) {
nsString a(password);
char* str = a.ToNewCString();
Recycle(password);
return str;
}
}
return nsnull;
}
void ApplicationFreeCallback(char *userInput)
{
nsMemory::Free(userInput);
}
char * FilePathPromptCallback(void *arg, char *prompt, char *fileRegEx, CMUint32 shouldFileExist)
{
nsresult rv = NS_OK;
char* filePath = nsnull;
NS_WITH_PROXIED_SERVICE(nsIPSMUIHandler, handler, nsPSMUIHandlerImpl::GetCID(), NS_UI_THREAD_EVENTQ, &rv);
if(NS_SUCCEEDED(rv))
handler->PromptForFile(NS_ConvertASCIItoUCS2(prompt).GetUnicode(), fileRegEx, (PRBool)shouldFileExist, &filePath);
return filePath;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef _NSPSMUICALLBACKS_H
#define _NSPSMUICALLBACKS_H
#include "prtypes.h"
#include "cmtcmn.h"
#include "nsIPSMUIHandler.h"
PRStatus InitPSMUICallbacks(PCMT_CONTROL gControl);
PRStatus InitPSMEventLoop(PCMT_CONTROL gControl);
PRStatus DisplayPSMUIDialog(PCMT_CONTROL control, const char* pickledStatus, const char *hostName);
#define NS_PSMUIHANDLER_CID {0x15944e30, 0x601e, 0x11d3, {0x8c, 0x4a, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
class nsPSMUIHandlerImpl : public nsIPSMUIHandler
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR( NS_PSMUIHANDLER_CID );
/* ctor/dtor */
nsPSMUIHandlerImpl() { NS_INIT_REFCNT(); }
virtual ~nsPSMUIHandlerImpl() { }
NS_DECL_ISUPPORTS
NS_DECL_NSIPSMUIHANDLER
static NS_METHOD CreatePSMUIHandler(nsISupports* aOuter, REFNSIID aIID, void **aResult);
};
#endif

View File

@@ -0,0 +1,320 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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):
* thayes@netscape.com
*/
#include "stdlib.h"
#include "plstr.h"
#include "nsMemory.h"
#include "nsIServiceManager.h"
#include "plbase64.h"
#include "nsISecretDecoderRing.h"
#include "cmtcmn.h"
#include "nsIPSMComponent.h"
#include "nsSDR.h"
NS_IMPL_ISUPPORTS1(nsSecretDecoderRing, nsISecretDecoderRing)
nsSecretDecoderRing::nsSecretDecoderRing()
{
NS_INIT_ISUPPORTS();
mPSM = NULL;
}
nsSecretDecoderRing::~nsSecretDecoderRing()
{
if (mPSM) mPSM->Release();
}
/* Init the new instance */
nsresult nsSecretDecoderRing::
init()
{
nsresult rv;
nsISupports *psm;
rv = nsServiceManager::GetService(kPSMComponentProgID, NS_GET_IID(nsIPSMComponent),
&psm);
if (rv != NS_OK) goto loser; /* Should promote error */
mPSM = (nsIPSMComponent *)psm;
loser:
return rv;
}
/* [noscript] long encrypt (in buffer data, in long dataLen, out buffer result); */
NS_IMETHODIMP nsSecretDecoderRing::
Encrypt(unsigned char * data, PRInt32 dataLen, unsigned char * *result, PRInt32 *_retval)
{
nsresult rv = NS_OK;
unsigned char *r = 0;
CMT_CONTROL *control;
CMTStatus status;
CMUint32 cLen;
if (data == nsnull || result == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
/* Check object initialization */
NS_ASSERTION(mPSM != nsnull, "SDR object not initialized");
if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; }
/* Get the control connect to use for the request */
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
status = CMT_SDREncrypt(control, (void *)0, (const unsigned char *)0, 0,
data, dataLen, result, &cLen);
if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* XXX */
/* Copy returned data to nsMemory buffer ? */
*_retval = cLen;
loser:
return rv;
}
/* [noscript] long decrypt (in buffer data, in long dataLen, out buffer result); */
NS_IMETHODIMP nsSecretDecoderRing::
Decrypt(unsigned char * data, PRInt32 dataLen, unsigned char * *result, PRInt32 *_retval)
{
nsresult rv = NS_OK;
CMTStatus status;
CMT_CONTROL *control;
CMUint32 len;
if (data == nsnull || result == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
/* Check object initialization */
NS_ASSERTION(mPSM != nsnull, "SDR object not initialized");
if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; }
/* Get the control connection */
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
/* Call PSM to decrypt the value */
status = CMT_SDRDecrypt(control, (void *)0, data, dataLen, result, &len);
if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* Promote? */
/* Copy returned data to nsMemory buffer ? */
*_retval = len;
loser:
return rv;
}
/* string encryptString (in string text); */
NS_IMETHODIMP nsSecretDecoderRing::
EncryptString(const char *text, char **_retval)
{
nsresult rv = NS_OK;
unsigned char *encrypted = 0;
PRInt32 eLen;
if (text == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
rv = Encrypt((unsigned char *)text, PL_strlen(text), &encrypted, &eLen);
if (rv != NS_OK) { goto loser; }
rv = encode(encrypted, eLen, _retval);
loser:
if (encrypted) nsMemory::Free(encrypted);
return rv;
}
/* string decryptString (in string crypt); */
NS_IMETHODIMP nsSecretDecoderRing::
DecryptString(const char *crypt, char **_retval)
{
nsresult rv = NS_OK;
char *r = 0;
unsigned char *decoded = 0;
PRInt32 decodedLen;
unsigned char *decrypted = 0;
PRInt32 decryptedLen;
if (crypt == nsnull || _retval == nsnull) {
rv = NS_ERROR_INVALID_POINTER;
goto loser;
}
rv = decode(crypt, &decoded, &decodedLen);
if (rv != NS_OK) goto loser;
rv = Decrypt(decoded, decodedLen, &decrypted, &decryptedLen);
if (rv != NS_OK) goto loser;
// Convert to NUL-terminated string
r = (char *)nsMemory::Alloc(decryptedLen+1);
if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
memcpy(r, decrypted, decryptedLen);
r[decryptedLen] = 0;
*_retval = r;
r = 0;
loser:
if (r) nsMemory::Free(r);
if (decrypted) nsMemory::Free(decrypted);
if (decoded) nsMemory::Free(decoded);
return rv;
}
/* void changePassword(); */
NS_IMETHODIMP nsSecretDecoderRing::
ChangePassword()
{
nsresult rv = NS_OK;
CMTStatus status;
CMT_CONTROL *control;
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
status = CMT_SDRChangePassword(control, (void*)0);
loser:
return rv;
}
/* void logout(); */
NS_IMETHODIMP nsSecretDecoderRing::
Logout()
{
nsresult rv = NS_OK;
CMTStatus status;
CMT_CONTROL *control;
/* Check object initialization */
NS_ASSERTION(mPSM != nsnull, "SDR object not initialized");
if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; }
/* Get the control connection */
rv = mPSM->GetControlConnection(&control);
if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
/* Call PSM to decrypt the value */
status = CMT_LogoutAllTokens(control);
if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* Promote? */
loser:
return rv;
}
// Support routines
nsresult nsSecretDecoderRing::
encode(const unsigned char *data, PRInt32 dataLen, char **_retval)
{
nsresult rv = NS_OK;
*_retval = PL_Base64Encode((const char *)data, dataLen, NULL);
if (!*_retval) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
loser:
return rv;
#if 0
nsresult rv = NS_OK;
char *r = 0;
// Allocate space for encoded string (with NUL)
r = (char *)nsMemory::Alloc(dataLen+1);
if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
memcpy(r, data, dataLen);
r[dataLen] = 0;
*_retval = r;
r = 0;
loser:
if (r) nsMemory::Free(r);
return rv;
#endif
}
nsresult nsSecretDecoderRing::
decode(const char *data, unsigned char **result, PRInt32 * _retval)
{
nsresult rv = NS_OK;
PRUint32 len = PL_strlen(data);
int adjust = 0;
/* Compute length adjustment */
if (data[len-1] == '=') {
adjust++;
if (data[len-2] == '=') adjust++;
}
*result = (unsigned char *)PL_Base64Decode(data, len, NULL);
if (!*result) { rv = NS_ERROR_ILLEGAL_VALUE; goto loser; }
*_retval = (len*3)/4 - adjust;
loser:
return rv;
#if 0
nsresult rv = NS_OK;
unsigned char *r = 0;
PRInt32 rLen;
// Allocate space for decoded string (missing NUL)
rLen = PL_strlen(data);
r = (unsigned char *)nsMemory::Alloc(rLen);
if (!r) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
memcpy(r, data, rLen);
*result = r;
r = 0;
*_retval = rLen;
loser:
if (r) nsMemory::Free(r);
return rv;
#endif
}
const char * nsSecretDecoderRing::kPSMComponentProgID = PSM_COMPONENT_PROGID;

View File

@@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Terry Hayes <thayes@netscape.com>
*/
#ifndef _NSSDR_H_
#define _NSSDR_H_
#include "nsISecretDecoderRing.h"
// ===============================================
// nsSecretDecoderRing - implementation of nsISecretDecoderRing
// ===============================================
#define NS_SDR_CLASSNAME "Secret Decoder Ring"
#define NS_SDR_CID \
{ 0xd9a0341, 0xce7, 0x11d4, { 0x9f, 0xdd, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
#define NS_SDR_PROGID "netscape.security.sdr"
class nsSecretDecoderRing : public nsISecretDecoderRing
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISECRETDECODERRING
nsSecretDecoderRing();
virtual ~nsSecretDecoderRing();
nsresult init();
private:
nsIPSMComponent *mPSM;
static const char *kPSMComponentProgID;
nsresult encode(const unsigned char *data, PRInt32 dataLen, char **_retval);
nsresult decode(const char *data, unsigned char **result, PRInt32 * _retval);
};
#endif /* _NSSDR_H_ */

View File

@@ -0,0 +1,550 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nspr.h"
#include "nsString.h"
#include "cmtcmn.h"
#include "nsIPSMComponent.h"
#include "nsIPSMSocketInfo.h"
#include "nsIServiceManager.h"
#include "nsPSMShimLayer.h"
#include "nsSSLIOLayer.h"
static PRDescIdentity nsSSLIOLayerIdentity;
static PRIOMethods nsSSLIOLayerMethods;
static nsIPSMComponent* gPSMService = nsnull;
class nsPSMSocketInfo : public nsIPSMSocketInfo
{
public:
nsPSMSocketInfo();
virtual ~nsPSMSocketInfo();
NS_DECL_ISUPPORTS
NS_DECL_NSIPSMSOCKETINFO
// internal functions to psm-glue.
nsresult SetSocketPtr(CMSocket *socketPtr);
nsresult SetControlPtr(CMT_CONTROL *aControlPtr);
nsresult SetFileDescPtr(PRFileDesc *aControlPtr);
nsresult SetHostName(char *aHostName);
nsresult SetProxyName(char *aName);
nsresult SetHostPort(PRInt32 aPort);
nsresult SetProxyPort(PRInt32 aPort);
nsresult SetPickledStatus();
protected:
CMT_CONTROL* mControl;
CMSocket* mSocket;
PRFileDesc* mFd;
nsString mHostName;
PRInt32 mHostPort;
nsString mProxyName;
PRInt32 mProxyPort;
unsigned char* mPickledStatus;
};
static PRStatus PR_CALLBACK
nsSSLIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
{
nsresult result;
PRStatus rv = PR_SUCCESS;
CMTStatus status = CMTFailure;
/* Set the error in case of failure. */
PR_SetError(PR_UNKNOWN_ERROR, status);
if (!fd || !addr || !fd->secret || !gPSMService)
return PR_FAILURE;
char ipBuffer[PR_NETDB_BUF_SIZE];
rv = PR_NetAddrToString(addr, (char*)&ipBuffer, PR_NETDB_BUF_SIZE);
if (rv != PR_SUCCESS)
return PR_FAILURE;
if (addr->raw.family == PR_AF_INET6 && PR_IsNetAddrType(addr, PR_IpAddrV4Mapped))
{
/* Chop off the leading "::ffff:" */
strcpy(ipBuffer, ipBuffer + 7);
}
CMT_CONTROL *control;
result = gPSMService->GetControlConnection(&control);
if (result != PR_SUCCESS)
return PR_FAILURE;
CMSocket* cmsock = (CMSocket *)PR_Malloc(sizeof(CMSocket));
if (!cmsock)
return PR_FAILURE;
memset(cmsock, 0, sizeof(CMSocket));
cmsock->fd = fd->lower;
cmsock->isUnix = PR_FALSE;
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
infoObject->SetControlPtr(control);
infoObject->SetSocketPtr(cmsock);
char* proxyName;
char* hostName;
infoObject->GetProxyName(&proxyName);
infoObject->GetHostName(&hostName);
if (!proxyName)
{
// Direct connection
status = CMT_OpenSSLConnection(control,
cmsock,
SSM_REQUEST_SSL_DATA_SSL,
PR_ntohs(addr->inet.port),
ipBuffer,
(hostName ? hostName : ipBuffer),
CM_FALSE,
nsnull);
}
else
{
// not supported yet.
return PR_FAILURE;
#if 0
PRInt32 destPort;
infoObject->GetProxyPort(&destPort);
status = CMT_OpenSSLProxyConnection(control,
cmsock,
destPort,
proxyName, // wants IP
hostName);
#endif
}
if (hostName) Recycle(hostName);
if (proxyName) Recycle(proxyName);
if (CMTSuccess == status)
{
// since our stuff can block, what we want to do is return PR_FAILURE,
// but set the nspr ERROR to BLOCK. This will put us into a select
// q.
PR_SetError(PR_WOULD_BLOCK_ERROR, status);
return PR_FAILURE;
}
return PR_FAILURE;
}
/* CMT_DestroyDataConnection(ctrl, sock); */
/* need to strip our layer, pass result to DestroyDataConnection */
/* which will clean up the CMT accounting of sock, then call our */
/* shim layer to translate back to NSPR */
static PRStatus PR_CALLBACK
nsSSLIOLayerClose(PRFileDesc *fd)
{
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (infoObject && id == nsSSLIOLayerIdentity)
{
CMInt32 errorCode = PR_FAILURE;
CMT_CONTROL* control;
CMSocket* socket;
PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
infoObject->GetControlPtr(&control);
infoObject->GetSocketPtr(&socket);
infoObject->SetPickledStatus();
CMT_GetSSLDataErrorCode(control, socket, &errorCode);
CMT_DestroyDataConnection(control, socket);
NS_RELEASE(infoObject); // if someone is interested in us, the better have an addref.
fd->identity = PR_INVALID_IO_LAYER;
return (PRStatus)errorCode;
}
return PR_FAILURE;
}
static PRInt32 PR_CALLBACK
nsSSLIOLayerRead( PRFileDesc *fd, void *buf, PRInt32 amount)
{
if (!fd)
return PR_FAILURE;
PRInt32 result = PR_Recv(fd, buf, amount, 0, PR_INTERVAL_MIN);
if (result > 0)
return result;
if (result == -1)
{
PRErrorCode code = PR_GetError();
if (code == PR_IO_TIMEOUT_ERROR )
PR_SetError(PR_WOULD_BLOCK_ERROR, PR_WOULD_BLOCK_ERROR);
return PR_FAILURE;
}
if (result == 0)
{
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (infoObject && id == nsSSLIOLayerIdentity)
{
CMInt32 errorCode = PR_FAILURE;
CMT_CONTROL* control;
CMSocket* socket;
infoObject->GetControlPtr(&control);
infoObject->GetSocketPtr(&socket);
CMT_GetSSLDataErrorCode(control, socket, &errorCode);
if (errorCode == PR_IO_TIMEOUT_ERROR)
{
PR_SetError(PR_WOULD_BLOCK_ERROR, PR_WOULD_BLOCK_ERROR);
return PR_FAILURE;
}
PR_SetError(0, 0);
return errorCode;
}
}
return result;
}
static PRInt32 PR_CALLBACK
nsSSLIOLayerWrite( PRFileDesc *fd, const void *buf, PRInt32 amount)
{
if (!fd)
return PR_FAILURE;
PRInt32 result = PR_Send(fd, buf, amount, 0, PR_INTERVAL_MIN);
if (result > 0)
return result;
if (result == -1)
{
PRErrorCode code = PR_GetError();
if (code == PR_IO_TIMEOUT_ERROR )
PR_SetError(PR_WOULD_BLOCK_ERROR, PR_WOULD_BLOCK_ERROR);
return PR_FAILURE;
}
if (result == 0)
{
nsPSMSocketInfo *infoObject = (nsPSMSocketInfo *)fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (infoObject && id == nsSSLIOLayerIdentity)
{
CMInt32 errorCode = PR_FAILURE;
CMT_CONTROL* control;
CMSocket* socket;
infoObject->GetControlPtr(&control);
infoObject->GetSocketPtr(&socket);
CMT_GetSSLDataErrorCode(control, socket, &errorCode);
PR_SetError(0, 0);
return errorCode;
}
}
return result;
}
nsPSMSocketInfo::nsPSMSocketInfo()
{
NS_INIT_REFCNT();
mControl = nsnull;
mSocket = nsnull;
mPickledStatus = nsnull;
}
nsPSMSocketInfo::~nsPSMSocketInfo()
{
PR_FREEIF(mPickledStatus);
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsPSMSocketInfo, nsIPSMSocketInfo);
NS_IMETHODIMP
nsPSMSocketInfo::GetControlPtr(CMT_CONTROL * *aControlPtr)
{
*aControlPtr = mControl;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetControlPtr(CMT_CONTROL *aControlPtr)
{
mControl = aControlPtr;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetSocketPtr(CMSocket * *socketPtr)
{
*socketPtr = mSocket;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetSocketPtr(CMSocket *socketPtr)
{
mSocket = socketPtr;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetFileDescPtr(PRFileDesc * *aFilePtr)
{
*aFilePtr = mFd;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetFileDescPtr(PRFileDesc *aFilePtr)
{
mFd = aFilePtr;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetHostName(char * *aHostName)
{
if (mHostName.IsEmpty())
*aHostName = nsnull;
else
*aHostName = mHostName.ToNewCString();
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetHostName(char *aHostName)
{
mHostName.AssignWithConversion(aHostName);
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetHostPort(PRInt32 *aPort)
{
*aPort = mHostPort;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetHostPort(PRInt32 aPort)
{
mHostPort = aPort;
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetProxyName(char * *aName)
{
if (mProxyName.IsEmpty())
*aName = nsnull;
else
*aName = mProxyName.ToNewCString();
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetProxyName(char *aName)
{
mProxyName.AssignWithConversion(aName);
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetProxyPort(PRInt32 *aPort)
{
*aPort = mProxyPort;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetProxyPort(PRInt32 aPort)
{
mProxyPort = aPort;
return NS_OK;
}
nsresult
nsPSMSocketInfo::SetPickledStatus()
{
PR_FREEIF(mPickledStatus);
long level;
CMTItem pickledStatus = {0, nsnull, 0};
unsigned char* ret = nsnull;
if (CMT_GetSSLSocketStatus(mControl, mSocket, &pickledStatus, &level) != PR_FAILURE)
{
ret = (unsigned char*) PR_Malloc( (SSMSTRING_PADDED_LENGTH(pickledStatus.len) + sizeof(int)) );
if (ret)
{
*(int*)ret = pickledStatus.len;
memcpy(ret+sizeof(int), pickledStatus.data, *(int*)ret);
}
PR_FREEIF(pickledStatus.data);
mPickledStatus = ret;
}
return NS_OK;
}
NS_IMETHODIMP
nsPSMSocketInfo::GetPickledStatus(char * *pickledStatusString)
{
if (!mPickledStatus)
SetPickledStatus();
if (mPickledStatus)
{
PRInt32 len = *(int*)mPickledStatus;
char *out = (char *)nsMemory::Alloc(len);
memcpy(out, mPickledStatus, len);
*pickledStatusString = out;
return NS_OK;
}
*pickledStatusString = nsnull;
return NS_ERROR_FAILURE;
}
nsresult
nsSSLIOLayerNewSocket( const char *host,
PRInt32 port,
const char *proxyHost,
PRInt32 proxyPort,
PRFileDesc **fd,
nsISupports** info)
{
static PRBool firstTime = PR_TRUE;
if (firstTime)
{
nsSSLIOLayerIdentity = PR_GetUniqueIdentity("Cartman layer");
nsSSLIOLayerMethods = *PR_GetDefaultIOMethods();
nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect;
nsSSLIOLayerMethods.close = nsSSLIOLayerClose;
nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
nsSSLIOLayerMethods.write = nsSSLIOLayerWrite;
nsresult result = nsServiceManager::GetService( PSM_COMPONENT_PROGID,
NS_GET_IID(nsIPSMComponent),
(nsISupports**)&gPSMService);
if (NS_FAILED(result))
return PR_FAILURE;
firstTime = PR_FALSE;
}
PRFileDesc * sock;
PRFileDesc * layer;
PRStatus rv;
/* Get a normal NSPR socket */
sock = PR_NewTCPSocket();
if (! sock) return NS_ERROR_OUT_OF_MEMORY;
/* disable Nagle algorithm delay for control sockets */
PRSocketOptionData sockopt;
sockopt.option = PR_SockOpt_NoDelay;
sockopt.value.no_delay = PR_TRUE;
rv = PR_SetSocketOption(sock, &sockopt);
PR_ASSERT(PR_SUCCESS == rv);
layer = PR_CreateIOLayerStub(nsSSLIOLayerIdentity, &nsSSLIOLayerMethods);
if (! layer)
{
PR_Close(sock);
return NS_ERROR_FAILURE;
}
nsPSMSocketInfo *infoObject = new nsPSMSocketInfo();
if (!infoObject)
{
PR_Close(sock);
// clean up IOLayerStub.
return NS_ERROR_FAILURE;
}
NS_ADDREF(infoObject);
infoObject->SetHostName((char*)host);
infoObject->SetHostPort(port);
infoObject->SetProxyName((char*)proxyHost);
infoObject->SetProxyPort(proxyPort);
layer->secret = (PRFilePrivate*) infoObject;
rv = PR_PushIOLayer(sock, PR_GetLayersIdentity(sock), layer);
if (rv == PR_SUCCESS)
{
*fd = sock;
*info = infoObject;
NS_ADDREF(*info);
return NS_OK;
}
PR_Close(sock);
return NS_ERROR_FAILURE;
}

View File

@@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _NSSSLIOLAYER_H
#define _NSSSLIOLAYER_H
#include "prtypes.h"
#include "prio.h"
#include "nsIPSMSocketInfo.h"
// define taken from 4.x cartman glue code.
#define SSMSTRING_PADDED_LENGTH(x) ((((x)+3)/4)*4)
nsresult nsSSLIOLayerNewSocket(const char *host,
PRInt32 port,
const char *proxyHost,
PRInt32 proxyPort,
PRFileDesc **fd,
nsISupports **securityInfo);
#endif /* _NSSSLIOLAYER_H */

View File

@@ -0,0 +1,94 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsSSLSocketProvider.h"
#include "nsSSLIOLayer.h"
////////////////////////////////////////////////////////////////////////////////
nsSSLSocketProvider::nsSSLSocketProvider()
{
NS_INIT_REFCNT();
}
nsresult
nsSSLSocketProvider::Init()
{
nsresult rv = NS_OK;
return rv;
}
nsSSLSocketProvider::~nsSSLSocketProvider()
{
}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsSSLSocketProvider, nsISocketProvider, nsISSLSocketProvider);
NS_METHOD
nsSSLSocketProvider::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsSSLSocketProvider * inst;
if (NULL == aResult) {
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = NULL;
if (NULL != aOuter) {
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
NS_NEWXPCOM(inst, nsSSLSocketProvider);
if (NULL == inst) {
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
NS_IMETHODIMP
nsSSLSocketProvider::NewSocket(const char *host,
PRInt32 port,
const char *proxyHost,
PRInt32 proxyPort,
PRFileDesc **_result,
nsISupports **securityInfo)
{
nsresult rv = nsSSLIOLayerNewSocket(host,
port,
proxyHost,
proxyPort,
_result,
securityInfo);
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
}

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _NSSSLSOCKETPROVIDER_H_
#define _NSSSLSOCKETPROVIDER_H_
#include "nsISSLSocketProvider.h"
/* 274418d0-5437-11d3-bbc8-0000861d1237 */
#define NS_SSLSOCKETPROVIDER_CID { 0x274418d0, 0x5437, 0x11d3, {0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37}}
class nsSSLSocketProvider : public nsISSLSocketProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISOCKETPROVIDER
NS_DECL_NSISSLSOCKETPROVIDER
// nsSSLSocketProvider methods:
nsSSLSocketProvider();
virtual ~nsSSLSocketProvider();
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
nsresult Init();
protected:
};
#endif /* _NSSSLSOCKETPROVIDER_H_ */

View File

@@ -0,0 +1,654 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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) 1998-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nspr.h"
#include "prlog.h"
#include "nsISecureBrowserUI.h"
#include "nsSecureBrowserUIImpl.h"
#include "nsIPSMComponent.h"
#include "nsPSMComponent.h"
#include "nsCOMPtr.h"
#include "nsIInterfaceRequestor.h"
#include "nsIServiceManager.h"
#include "nsIScriptGlobalObject.h"
#include "nsIObserverService.h"
#include "nsIDocumentLoader.h"
#include "nsCURILoader.h"
#include "nsIDocShell.h"
#include "nsIDocumentViewer.h"
#include "nsCURILoader.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMWindow.h"
#include "nsIContent.h"
#include "nsIWebProgress.h"
#include "nsIChannel.h"
#include "nsIPSMSocketInfo.h"
#include "nsIURI.h"
#include "prmem.h"
#include "nsINetSupportDialogService.h"
#include "nsIPrompt.h"
#include "nsICommonDialogs.h"
#include "nsIPref.h"
#include "nsIFormSubmitObserver.h"
static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
static NS_DEFINE_CID(kCommonDialogsCID, NS_CommonDialog_CID );
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
#define ENTER_SITE_PREF "security.warn_entering_secure"
#define LEAVE_SITE_PREF "security.warn_leaving_secure"
#define MIXEDCONTENT_PREF "security.warn_viewing_mixed"
#define INSECURE_SUBMIT_PREF "security.warn_submit_insecure"
#if defined(PR_LOGGING)
//
// Log module for nsSecureBroswerUI logging...
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsSecureBroswerUI:5
// set NSPR_LOG_FILE=nspr.log
//
// this enables PR_LOG_DEBUG level information and places all output in
// the file nspr.log
//
PRLogModuleInfo* gSecureDocLog = nsnull;
#endif /* PR_LOGGING */
NS_IMETHODIMP
nsSecureBrowserUIImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsSecureBrowserUIImpl * inst;
if (NULL == aResult) {
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = NULL;
if (NULL != aOuter) {
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
NS_NEWXPCOM(inst, nsSecureBrowserUIImpl);
if (NULL == inst) {
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
nsSecureBrowserUIImpl::nsSecureBrowserUIImpl()
{
NS_INIT_REFCNT();
#if defined(PR_LOGGING)
if (nsnull == gSecureDocLog) {
gSecureDocLog = PR_NewLogModule("nsSecureBroswerUI");
}
#endif /* PR_LOGGING */
mIsSecureDocument = mMixContentAlertShown = mIsDocumentBroken = PR_FALSE;
mLastPSMStatus = nsnull;
mCurrentURI = nsnull;
mSecurityButton = nsnull;
}
nsSecureBrowserUIImpl::~nsSecureBrowserUIImpl()
{
PR_FREEIF(mLastPSMStatus);
}
NS_IMPL_ISUPPORTS4(nsSecureBrowserUIImpl,
nsSecureBrowserUI,
nsIWebProgressListener,
nsIFormSubmitObserver,
nsIObserver);
NS_IMETHODIMP
nsSecureBrowserUIImpl::Init(nsIDOMWindow *window, nsIDOMElement *button)
{
mSecurityButton = button;
mWindow = window;
nsresult rv = nsServiceManager::GetService( kPrefCID,
NS_GET_IID(nsIPref),
getter_AddRefs(mPref));
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIStringBundleService, service, kCStringBundleServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsILocale* locale = nsnull;
rv = service->CreateBundle(SECURITY_STRING_BUNDLE_URL, locale, getter_AddRefs(mStringBundle));
if (NS_FAILED(rv)) return rv;
// hook up to the form post notifications:
nsIObserverService *svc = 0;
rv = nsServiceManager::GetService(NS_OBSERVERSERVICE_PROGID,
NS_GET_IID(nsIObserverService),
(nsISupports**)&svc );
if (NS_SUCCEEDED(rv) && svc) {
nsString topic; topic.AssignWithConversion(NS_FORMSUBMIT_SUBJECT);
rv = svc->AddObserver( this, topic.GetUnicode());
nsServiceManager::ReleaseService( NS_OBSERVERSERVICE_PROGID, svc );
}
// hook up to the webprogress notifications.
nsCOMPtr<nsIDocShell> docShell;
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
if (!sgo) return NS_ERROR_NULL_POINTER;
sgo->GetDocShell(getter_AddRefs(docShell));
if (!docShell) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIWebProgress> wp = do_GetInterface(docShell);
if (!wp) return NS_ERROR_NULL_POINTER;
wp->AddProgressListener(NS_STATIC_CAST(nsIWebProgressListener*,this));
mInitByLocationChange = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::DisplayPageInfoUI()
{
nsresult res;
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &res);
if (NS_FAILED(res))
return res;
nsXPIDLCString host;
if (mCurrentURI)
mCurrentURI->GetHost(getter_Copies(host));
return psm->DisplaySecurityAdvisor(mLastPSMStatus, host);
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::Observe(nsISupports*, const PRUnichar*, const PRUnichar*)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static nsresult IsChildOfDomWindow(nsIDOMWindow *parent, nsIDOMWindow *child, PRBool* value)
{
*value = PR_FALSE;
if (parent == child)
{
*value = PR_TRUE;
return NS_OK;
}
nsCOMPtr<nsIDOMWindow> childsParent;
child->GetParent(getter_AddRefs(childsParent));
if (childsParent && childsParent.get() != child)
IsChildOfDomWindow(parent, childsParent, value);
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI* actionURL)
{
// Return NS_OK unless we want to prevent this form from submitting.
if (!window || !actionURL || !formNode) {
return NS_OK;
}
nsCOMPtr<nsIDocument> document;
formNode->GetDocument(*getter_AddRefs(document));
if (!document) return NS_OK;
nsCOMPtr<nsIScriptGlobalObject> globalObject;
document->GetScriptGlobalObject(getter_AddRefs(globalObject));
nsCOMPtr<nsIDOMWindow> postingWindow = do_QueryInterface(globalObject);
PRBool isChild;
IsChildOfDomWindow(mWindow, postingWindow, &isChild);
if (!isChild)
return NS_OK;
PRBool okayToPost;
nsresult res = CheckPost(actionURL, &okayToPost);
if (NS_SUCCEEDED(res) && okayToPost)
return NS_OK;
return NS_ERROR_FAILURE;
}
// nsIWebProgressListener
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress,
PRInt32 aMaxTotalProgress)
{
return NS_OK;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
PRInt32 aProgressStateFlags,
nsresult aStatus)
{
nsresult res = NS_OK;
if (aRequest == nsnull || !mSecurityButton || !mPref)
return NS_ERROR_NULL_POINTER;
// Get the channel from the request...
// If the request is not network based, then ignore it.
nsCOMPtr<nsIChannel> channel;
channel = do_QueryInterface(aRequest, &res);
if (NS_FAILED(res))
return NS_OK;
nsCOMPtr<nsIURI> loadingURI;
channel->GetURI(getter_AddRefs(loadingURI));
#if defined(DEBUG)
nsXPIDLCString temp;
loadingURI->GetSpec(getter_Copies(temp));
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: OnStateChange: %x :%s\n", this, aProgressStateFlags,(const char*)temp));
#endif
// A Document is starting to load...
if ((aProgressStateFlags & flag_start) &&
(aProgressStateFlags & flag_is_network))
{
// starting to load a webpage
PR_FREEIF(mLastPSMStatus); mLastPSMStatus = nsnull;
mIsSecureDocument = mMixContentAlertShown = mIsDocumentBroken = PR_FALSE;
res = CheckProtocolContextSwitch( loadingURI, mCurrentURI);
return res;
}
// A document has finished loading
if ((aProgressStateFlags & flag_stop) &&
(aProgressStateFlags & flag_is_network) &&
mIsSecureDocument)
{
if (!mIsDocumentBroken) // and status is okay FIX
{
// qi for the psm information about this channel load.
nsCOMPtr<nsISupports> info;
channel->GetSecurityInfo(getter_AddRefs(info));
nsCOMPtr<nsIPSMSocketInfo> psmInfo = do_QueryInterface(info);
if (psmInfo)
{
// Everything looks okay. Lets stash the picked status.
PR_FREEIF(mLastPSMStatus);
res = psmInfo->GetPickledStatus(&mLastPSMStatus);
if (NS_SUCCEEDED(res)) {
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: Icon set to lock\n", this));
res = mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("high") );
return res;
}
}
}
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: Icon set to broken\n", this));
mIsDocumentBroken = PR_TRUE;
res = mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("broken"));
return res;
}
/// if (aProgressStateFlags == nsIWebProgress::flag_net_redirecting)
/// {
/// // need to implmentent.
/// }
// don't need to do anything more if the page is broken or not secure...
if (!mIsSecureDocument || mIsDocumentBroken)
return NS_OK;
// A URL is starting to load...
if ((aProgressStateFlags & flag_start) &&
(aProgressStateFlags & flag_is_request))
{ // check to see if we are going to mix content.
return CheckMixedContext(loadingURI);
}
// A URL has finished loading...
if ((aProgressStateFlags & flag_stop) &&
(aProgressStateFlags & flag_is_request))
{
if (1) // FIX status from the flag...
{
nsCOMPtr<nsISupports> info;
channel->GetSecurityInfo(getter_AddRefs(info));
nsCOMPtr<nsIPSMSocketInfo> psmInfo = do_QueryInterface(info, &res);
// qi for the psm information about this channel load.
if (psmInfo) {
return NS_OK;
}
}
PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: OnStateChange - Icon set to broken\n", this));
mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("broken") );
mIsDocumentBroken = PR_TRUE;
}
return res;
}
NS_IMETHODIMP
nsSecureBrowserUIImpl::OnLocationChange(nsIURI* aLocation)
{
mCurrentURI = aLocation;
if (mInitByLocationChange)
{
IsURLHTTPS(mCurrentURI, &mIsSecureDocument);
mInitByLocationChange = PR_FALSE;
}
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::IsURLHTTPS(nsIURI* aURL, PRBool* value)
{
*value = PR_FALSE;
if (!aURL)
return NS_OK;
char* scheme;
aURL->GetScheme(&scheme);
if (scheme == nsnull)
return NS_ERROR_NULL_POINTER;
if ( PL_strncasecmp(scheme, "https", 5) == 0 )
*value = PR_TRUE;
nsMemory::Free(scheme);
return NS_OK;
}
void nsSecureBrowserUIImpl::GetBundleString(const nsString& name, nsString &outString)
{
if (mStringBundle && name.Length() > 0) {
PRUnichar *ptrv = nsnull;
if (NS_SUCCEEDED(mStringBundle->GetStringFromName(name.GetUnicode(), &ptrv)))
outString = ptrv;
else
outString.SetLength(0);;
nsMemory::Free(ptrv);
} else {
outString.SetLength(0);;
}
}
nsresult
nsSecureBrowserUIImpl::CheckProtocolContextSwitch( nsIURI* newURI, nsIURI* oldURI)
{
nsresult res;
PRBool isNewSchemeSecure, isOldSchemeSecure, boolpref;
res = IsURLHTTPS(oldURI, &isOldSchemeSecure);
if (NS_FAILED(res))
return res;
res = IsURLHTTPS(newURI, &isNewSchemeSecure);
if (NS_FAILED(res))
return res;
// Check to see if we are going from a secure page to and insecure page
if ( !isNewSchemeSecure && isOldSchemeSecure)
{
mSecurityButton->RemoveAttribute( NS_ConvertASCIItoUCS2("level") );
if ((mPref->GetBoolPref(LEAVE_SITE_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &res);
if (NS_FAILED(res))
return res;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("LeaveSiteMessage"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->AlertCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue);
if (!outCheckValue) {
mPref->SetBoolPref(LEAVE_SITE_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &res);
if (NS_FAILED(res))
return res;
psm->PassPrefs();
}
}
}
// check to see if we are going from an insecure page to a secure one.
else if (isNewSchemeSecure && !isOldSchemeSecure)
{
if ((mPref->GetBoolPref(ENTER_SITE_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &res);
if (NS_FAILED(res))
return res;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("EnterSiteMessage"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->AlertCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue);
if (!outCheckValue)
{
mPref->SetBoolPref(ENTER_SITE_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &res);
if (NS_FAILED(res))
return res;
psm->PassPrefs();
}
}
}
mIsSecureDocument = isNewSchemeSecure;
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::CheckMixedContext(nsIURI* nextURI)
{
PRBool secure;
nsresult rv = IsURLHTTPS(nextURI, &secure);
if (NS_FAILED(rv))
return rv;
if (!secure && mIsSecureDocument)
{
mIsDocumentBroken = PR_TRUE;
mSecurityButton->SetAttribute( NS_ConvertASCIItoUCS2("level"), NS_ConvertASCIItoUCS2("broken") );
if (!mPref) return NS_ERROR_NULL_POINTER;
PRBool boolpref;
if ((mPref->GetBoolPref(MIXEDCONTENT_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref && !mMixContentAlertShown)
{
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &rv);
if (NS_FAILED(rv))
return rv;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("MixedContentMessage"), message);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
PRBool outCheckValue = PR_TRUE;
dialog->AlertCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue);
if (!outCheckValue) {
mPref->SetBoolPref(MIXEDCONTENT_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &rv);
if (NS_FAILED(rv))
return rv;
psm->PassPrefs();
}
mMixContentAlertShown = PR_TRUE;
}
}
return NS_OK;
}
nsresult
nsSecureBrowserUIImpl::CheckPost(nsIURI *actionURL, PRBool *okayToPost)
{
PRBool secure;
nsresult rv = IsURLHTTPS(actionURL, &secure);
if (NS_FAILED(rv))
return rv;
// if we are posting to a secure link from a secure page, all is okay.
if (secure && mIsSecureDocument)
return NS_OK;
PRBool boolpref;
// posting to a non https URL.
if ((mPref->GetBoolPref(INSECURE_SUBMIT_PREF, &boolpref) != 0))
boolpref = PR_TRUE;
if (boolpref) {
NS_WITH_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, &rv);
if (NS_FAILED(rv))
return rv;
nsAutoString windowTitle, message, dontShowAgain;
GetBundleString(NS_ConvertASCIItoUCS2("Title"), windowTitle);
GetBundleString(NS_ConvertASCIItoUCS2("DontShowAgain"), dontShowAgain);
// posting to insecure webpage from a secure webpage.
if (!secure && mIsSecureDocument && !mIsDocumentBroken) {
GetBundleString(NS_ConvertASCIItoUCS2("PostToInsecure"), message);
} else { // anything else, post generic warning
GetBundleString(NS_ConvertASCIItoUCS2("PostToInsecureFromInsecure"), message);
}
PRBool outCheckValue = PR_TRUE;
dialog->ConfirmCheck(mWindow,
windowTitle.GetUnicode(),
message.GetUnicode(),
dontShowAgain.GetUnicode(),
&outCheckValue,
okayToPost);
if (!outCheckValue) {
mPref->SetBoolPref(INSECURE_SUBMIT_PREF, PR_FALSE);
NS_WITH_SERVICE(nsIPSMComponent, psm, PSM_COMPONENT_PROGID, &rv);
if (NS_FAILED(rv))
return rv;
psm->PassPrefs();
}
} else {
*okayToPost = PR_TRUE;
}
return NS_OK;
}

View File

@@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
*/
#ifndef nsSecureBrowserUIImpl_h_
#define nsSecureBrowserUIImpl_h_
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsString.h"
#include "nsIObserver.h"
#include "nsIDocumentLoaderObserver.h"
#include "nsIDOMElement.h"
#include "nsIDOMWindow.h"
#include "nsIStringBundle.h"
#include "nsISecureBrowserUI.h"
#include "nsIDocShell.h"
#include "nsIPref.h"
#include "nsIWebProgressListener.h"
#include "nsIFormSubmitObserver.h"
#include "nsIURI.h"
#define NS_SECURE_BROWSER_DOCOBSERVER_CLASSNAME "Mozilla Secure Browser Doc Observer"
#define NS_SECURE_BROWSER_DOCOBSERVER_CID \
{0x97c06c30, 0xa145, 0x11d3, \
{0x8c, 0x7c, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c}}
#define NS_SECURE_BROWSER_DOCOBSERVER_PROGID "component://netscape/secure_browser_docobserver"
class nsSecureBrowserUIImpl : public nsSecureBrowserUI,
public nsIWebProgressListener,
public nsIFormSubmitObserver,
public nsIObserver
{
public:
nsSecureBrowserUIImpl();
virtual ~nsSecureBrowserUIImpl();
static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSSECUREBROWSERUI
// nsIObserver
NS_DECL_NSIOBSERVER
NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindow* window, nsIURI *actionURL);
protected:
nsCOMPtr<nsIDOMWindow> mWindow;
nsCOMPtr<nsIDOMElement> mSecurityButton;
nsCOMPtr<nsIDocumentLoaderObserver> mOldWebShellObserver;
nsCOMPtr<nsIPref> mPref;
nsCOMPtr<nsIStringBundle> mStringBundle;
nsCOMPtr<nsIURI> mCurrentURI;
PRBool mIsSecureDocument; // is https loaded
PRBool mIsDocumentBroken; //
PRBool mMixContentAlertShown;
PRBool mInitByLocationChange;
char* mLastPSMStatus;
void GetBundleString(const nsString& name, nsString &outString);
nsresult LoadStringBundle();
nsresult CheckProtocolContextSwitch( nsIURI* newURI, nsIURI* oldURI);
nsresult CheckMixedContext(nsIURI* nextURI);
nsresult CheckPost(nsIURI *actionURL, PRBool *okayToPost);
nsresult IsURLHTTPS(nsIURI* aURL, PRBool *value);
};
#endif /* nsSecureBrowserUIImpl_h_ */

View File

@@ -1,152 +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):
# 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 *****
CORE_DEPTH = ../../..
MODULE = nss
ifndef FREEBL_RECURSIVE_BUILD
LIBRARY_NAME = freebl
else
ifdef USE_PURE_32
CORE_DEPTH = ../../../..
LIBRARY_NAME = freebl_pure32
else
LIBRARY_NAME = freebl_hybrid
endif
endif
# same version as rest of freebl
LIBRARY_VERSION = _3
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
REQUIRES =
EXPORTS = \
blapit.h \
shsign.h \
ecl-exp.h \
$(NULL)
PRIVATE_EXPORTS = \
blapi.h \
secmpi.h \
secrng.h \
ec.h \
ecl.h \
ecl-curve.h \
$(NULL)
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c mpcpucache.c
ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h
ifdef NSS_ENABLE_ECC
ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
ec2_aff.c ec2_mont.c ec2_proj.c \
ec2_163.c ec2_193.c ec2_233.c \
ecp_aff.c ecp_jac.c ecp_mont.c \
ecp_192.c ecp_224.c \
ec_naf.c ecp_jm.c
else
ECL_SRCS = $(NULL)
endif
CSRCS = \
ldvector.c \
prng_fips1861.c \
sysrand.c \
sha_fast.c \
md2.c \
md5.c \
sha512.c \
alg2268.c \
arcfour.c \
arcfive.c \
desblapi.c \
des.c \
rijndael.c \
aeskeywrap.c \
dh.c \
ec.c \
pqg.c \
dsa.c \
rsa.c \
shvfy.c \
$(MPI_SRCS) \
$(ECL_SRCS) \
$(NULL)
ALL_CSRCS := $(CSRCS)
ALL_HDRS = \
blapi.h \
blapit.h \
des.h \
ec.h \
loader.h \
rijndael.h \
secmpi.h \
sha.h \
sha_fast.h \
shsign.h \
vis_proto.h \
$(NULL)
ifdef NSS_ENABLE_ECC
DEFINES += -DNSS_ENABLE_ECC
endif
ifdef AES_GEN_TBL
DEFINES += -DRIJNDAEL_GENERATE_TABLES
else
ifdef AES_GEN_TBL_M
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
else
ifdef AES_GEN_VAL
DEFINES += -DRIJNDAEL_GENERATE_VALUES
else
ifdef AES_GEN_VAL_M
DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
else
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
endif
endif
endif
endif

View File

@@ -1,278 +0,0 @@
#
# Makefile for MPI 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 MPI Arbitrary Precision Integer Arithmetic library.
#
# 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
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Netscape Communications Corporation
# Richard C. Swift (swift@netscape.com)
# 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: Makefile,v 1.21 2005-02-02 22:28:22 gerv%gerv.net Exp $
#
## 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 target.mk
CFLAGS+= $(XCFLAGS)
##
## 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=#-lmalloc#-lefence#-lm
##
## 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
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h mp_gf2m.h \
mp_gf2m-priv.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd invmod isprime lap dec2hex hex2dec primegen prng \
basecvt fact exptmod pi makeprime identest
LIBOBJS = mpprime.o mpmontg.o mplogic.o mp_gf2m.o mpi.o $(AS_OBJS)
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
APPHDRS = mpi-config.h mpi.h mplogic.h mp_gf2m.h mpprime.h
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "libmpi.a - arithmetic and prime testing library"
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.SUFFIXES: .c .o .i
.c.i:
$(CC) $(CFLAGS) -E $< > $@
#.c.o: $*.h $*.c
# $(CC) $(CFLAGS) -c $<
#---------------------------------------
$(LIBOBJS): $(LIBHDRS)
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mpi.o: mpi.c logtab.h $(LIBHDRS)
mplogic.o: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h mp_gf2m-priv.h $(LIBHDRS)
mpmontg.o: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
mpprime.o: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
mpi_mips.o: mpi_mips.s
$(CC) -o $@ $(ASFLAGS) -c mpi_mips.s
mpi_sparc.o : montmulf.h
mpv_sparcv9.s: vis_64.il mpv_sparc.c
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_64.il mpv_sparc.c
mpv_sparcv8.s: vis_64.il mpv_sparc.c
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_32.il mpv_sparc.c
montmulfv8.o montmulfv9.o mpv_sparcv8.o mpv_sparcv9.o : %.o : %.s
$(CC) -o $@ $(SOLARIS_ASM_FLAGS) -c $<
# This rule is used to build the .s sources, which are then hand optimized.
#montmulfv8.s montmulfv9.s : montmulf%.s : montmulf%.il montmulf.c montmulf.h
# $(CC) -o $@ $(SOLARIS_ASM_FLAGS) -S montmulf$*.il montmulf.c
libmpi.a: $(LIBOBJS)
ar -cvr libmpi.a $(LIBOBJS)
$(RANLIB) libmpi.a
lib libs: libmpi.a
mpi.i: mpi.h
#---------------------------------------
MPTESTOBJS = mptest1.o mptest2.o mptest3.o mptest3a.o mptest4.o mptest4a.o \
mptest4b.o mptest6.o mptest7.o mptest8.o mptest9.o mptestb.o
MPTESTS = $(MPTESTOBJS:.o=)
$(MPTESTOBJS): mptest%.o: tests/mptest-%.c $(LIBHDRS)
$(CC) $(CFLAGS) -o $@ -c $<
$(MPTESTS): mptest%: mptest%.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
tests: mptest1 mptest2 mptest3 mptest3a mptest4 mptest4a mptest4b mptest6 \
mptestb bbsrand
utests: mptest7 mptest8 mptest9
#---------------------------------------
EXTRAOBJS = bbsrand.o bbs_rand.o prng.o
UTILOBJS = primegen.o metime.o identest.o basecvt.o fact.o exptmod.o pi.o \
makeprime.o gcd.o invmod.o lap.o isprime.o \
dec2hex.o hex2dec.o
UTILS = $(UTILOBJS:.o=)
$(UTILS): % : %.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
$(UTILOBJS) $(EXTRAOBJS): %.o : utils/%.c $(LIBHDRS)
$(CC) $(CFLAGS) -o $@ -c $<
prng: prng.o bbs_rand.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
bbsrand: bbsrand.o bbs_rand.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
utils: $(UTILS) prng bbsrand
#---------------------------------------
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test.o: mpi-test.c test-info.c $(LIBHDRS)
$(CC) $(CFLAGS) -o $@ -c $<
mpi-test: mpi-test.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
mdxptest.o: mdxptest.c $(LIBHDRS) mpi-priv.h
mdxptest: mdxptest.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
mulsqr.o: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
$(CC) $(CFLAGS) -DMP_SQUARE=1 -o $@ -c mulsqr.c
mulsqr: mulsqr.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
#---------------------------------------
alltests: tests utests mpi-test
tools: $(TOOLS)
doc:
(cd doc; ./build)
clean:
rm -f *.o *.a *.i
rm -f core
rm -f *~ .*~
rm -f utils/*.o
rm -f utils/core
rm -f utils/*~ utils/.*~
clobber: clean
rm -f $(TOOLS) $(UTILS)
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f libmpi.a
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
# END

View File

@@ -1,280 +0,0 @@
#
# Makefile.win - gmake Makefile for building MPI with VACPP on OS/2
#
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
#
# 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
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Netscape Communications Corporation
#
# 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: Makefile.os2,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
#
## 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
CC=icc.exe
AS=alp.exe
##
## 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
##
## Define CFLAGS to contain any local options your compiler
## setup requires.
##
## Conditional compilation options are no longer here; see
## the file 'mpi-config.h' instead.
##
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
#OS/2
AS_SRCS = mpi_x86.asm
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
CFLAGS = /Ti+ -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
$(MPICMN)
ASFLAGS =
##
## 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=#-lmalloc#-lefence#-lm
##
## 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
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
AS_OBJS = $(AS_SRCS:.asm=.obj)
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "mpi.lib - arithmetic and prime testing library"
@ echo "mpi-test.exe - test driver (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.SUFFIXES: .c .obj .i .lib .exe .asm
.c.i:
$(CC) $(CFLAGS) -E $< > $@
.c.obj:
$(CC) $(CFLAGS) -c $<
.asm.obj:
$(AS) $(ASFLAGS) $<
.obj.exe:
$(CC) $(CFLAGS) -Fo$@ $<
#---------------------------------------
$(LIBOBJS): $(LIBHDRS)
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mpi.obj: mpi.c logtab.h $(LIBHDRS)
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
mpi_mips.obj: mpi_mips.s
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
mpi.lib: $(LIBOBJS)
ilib /out:mpi.lib $(LIBOBJS)
$(RANLIB) mpi.lib
lib libs: mpi.lib
#---------------------------------------
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
MPTESTS = $(MPTESTOBJS:.obj=.exe)
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
utests: mptest7.exe mptest8.exe mptest9.exe
#---------------------------------------
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
isprime.obj dec2hex.obj hex2dec.obj
UTILS = $(UTILOBJS:.obj=.exe)
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
utils: $(UTILS) prng.exe bbsrand.exe
#---------------------------------------
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
#---------------------------------------
alltests: tests utests mpi-test.exe
tools: $(TOOLS)
doc:
(cd doc; ./build)
clean:
rm -f *.obj *.lib *.pdb *.ilk
cd utils; rm -f *.obj *.lib *.pdb *.ilk
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f mpi.lib
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
print:
@echo LIBOBJS = $(LIBOBJS)
# END

View File

@@ -1,280 +0,0 @@
#
# Makefile.win - gmake Makefile for building MPI with MSVC on NT
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
#
# 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
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Netscape Communications Corporation
#
# 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: Makefile.win,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
#
## 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
CC=cl.exe
AS=ml.exe
##
## 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
##
## Define CFLAGS to contain any local options your compiler
## setup requires.
##
## Conditional compilation options are no longer here; see
## the file 'mpi-config.h' instead.
##
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
#NT
AS_SRCS = mpi_x86.asm
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
CFLAGS = -O2 -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
ASFLAGS = -Cp -Sn -Zi -coff -I.
##
## 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=#-lmalloc#-lefence#-lm
##
## 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
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
AS_OBJS = $(AS_SRCS:.asm=.obj)
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "mpi.lib - arithmetic and prime testing library"
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.SUFFIXES: .c .obj .i .lib .exe .asm
.c.i:
$(CC) $(CFLAGS) -E $< > $@
.c.obj:
$(CC) $(CFLAGS) -c $<
.asm.obj:
$(AS) $(ASFLAGS) -c $<
.obj.exe:
$(CC) $(CFLAGS) -Fo$@ $<
#---------------------------------------
$(LIBOBJS): $(LIBHDRS)
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mpi.obj: mpi.c logtab.h $(LIBHDRS)
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
mpi_mips.obj: mpi_mips.s
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
mpi.lib: $(LIBOBJS)
ar -cvr mpi.lib $(LIBOBJS)
$(RANLIB) mpi.lib
lib libs: mpi.lib
#---------------------------------------
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
MPTESTS = $(MPTESTOBJS:.obj=.exe)
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
utests: mptest7.exe mptest8.exe mptest9.exe
#---------------------------------------
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
isprime.obj dec2hex.obj hex2dec.obj
UTILS = $(UTILOBJS:.obj=.exe)
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
utils: $(UTILS) prng.exe bbsrand.exe
#---------------------------------------
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
#---------------------------------------
alltests: tests utests mpi-test.exe
tools: $(TOOLS)
doc:
(cd doc; ./build)
clean:
rm -f *.obj *.lib *.pdb *.ilk
cd utils; rm -f *.obj *.lib *.pdb *.ilk
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f mpi.lib
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
print:
@echo LIBOBJS = $(LIBOBJS)
# END

View File

@@ -1,799 +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 MPI Arbitrary Precision Integer Arithmetic
library.
The Initial Developer of the Original Code is
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Portions created by the Initial Developer are Copyright (C) 1997-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 *****
About the MPI Library
---------------------
The files 'mpi.h' and 'mpi.c' define a simple, arbitrary precision
signed integer arithmetic package. The implementation is not the most
efficient possible, but the code is small and should be fairly easily
portable to just about any machine that supports an ANSI C compiler,
as long as it is capable of at least 16-bit arithmetic (but also see
below for more on this).
This library was written with an eye to cryptographic applications;
thus, some care is taken to make sure that temporary values are not
left lying around in memory when they are no longer in use. This adds
some overhead for zeroing buffers before they are released back into
the free pool; however, it gives you the assurance that there is only
one copy of your important values residing in your process's address
space at a time. Obviously, it is difficult to guarantee anything, in
a pre-emptive multitasking environment, but this at least helps you
keep a lid on the more obvious ways your data can get spread around in
memory.
Using the Library
-----------------
To use the MPI library in your program, you must include the header:
#include "mpi.h"
This header provides all the type and function declarations you'll
need to use the library. Almost all the names defined by the library
begin with the prefix 'mp_', so it should be easy to keep them from
clashing with your program's namespace (he says, glibly, knowing full
well there are always pathological cases).
There are a few things you may want to configure about the library.
By default, the MPI library uses an unsigned short for its digit type,
and an unsigned int for its word type. The word type must be big
enough to contain at least two digits, for the primitive arithmetic to
work out. On my machine, a short is 2 bytes and an int is 4 bytes --
but if you have 64-bit ints, you might want to use a 4-byte digit and
an 8-byte word. I have tested the library using 1-byte digits and
2-byte words, as well. Whatever you choose to do, the things you need
to change are:
(1) The type definitions for mp_digit and mp_word.
(2) The macro DIGIT_FMT which tells mp_print() how to display a
single digit. This is just a printf() format string, so you
can adjust it appropriately.
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
largest value expressible in an mp_digit and an mp_word,
respectively.
Both the mp_digit and mp_word should be UNSIGNED integer types. The
code relies on having the full positive precision of the type used for
digits and words.
The remaining type definitions should be left alone, for the most
part. The code in the library does not make any significant
assumptions about the sizes of things, but there is little if any
reason to change the other parameters, so I would recommend you leave
them as you found them.
The library comes with a Perl script, 'types.pl', which will scan your
current Makefile settings, and attempt to find good definitions for
these types. It relies on a Unix sort of build environment, so it
probably won't work under MacOS or Windows, but it can be convenient
if you're porting to a new flavour of Unix. Just run 'types.pl' at
the command line, and it will spit out its results to the standard
output.
Conventions
-----------
Most functions in the library return a value of type mp_err. This
permits the library to communicate success or various kinds of failure
to the calling program. The return values currently defined are:
MP_OKAY - okay, operation succeeded, all's well
MP_YES - okay, the answer is yes (same as MP_OKAY)
MP_NO - okay, but answer is no (not MP_OKAY)
MP_MEM - operation ran out of memory
MP_RANGE - input parameter was out of range
MP_BADARG - an invalid input parameter was provided
MP_UNDEF - no output value is defined for this input
The only function which currently uses MP_UNDEF is mp_invmod().
Division by zero is undefined, but the division functions will return
MP_RANGE for a zero divisor. MP_BADARG usually means you passed a
bogus mp_int structure to the function. MP_YES and MP_NO are not used
by the library itself; they're defined so you can use them in your own
extensions.
If you need a readable interpretation of these error codes in your
program, you may also use the mp_strerror() function. This function
takes an mp_err as input, and returns a pointer to a human-readable
string describing the meaning of the error. These strings are stored
as constants within the library, so the caller should not attempt to
modify or free the memory associated with these strings.
The library represents values in signed-magnitude format. Values
strictly less than zero are negative, all others are considered
positive (zero is positive by fiat). You can access the 'sign' member
of the mp_int structure directly, but better is to use the mp_cmp_z()
function, to find out which side of zero the value lies on.
Most arithmetic functions have a single-digit variant, as well as the
full arbitrary-precision. An mp_digit is an unsigned value between 0
and DIGIT_MAX inclusive. The radix is available as RADIX. The number
of bits in a given digit is given as DIGIT_BIT.
Generally, input parameters are given before output parameters.
Unless otherwise specified, any input parameter can be re-used as an
output parameter, without confusing anything.
The basic numeric type defined by the library is an mp_int. Virtually
all the functions in the library take a pointer to an mp_int as one of
their parameters. An explanation of how to create and use these
<HR>
<A NAME="p23">
<H3>Problem 23:</H3>
structures follows. And so, without further ado...
Initialization and Cleanup
--------------------------
The basic numeric type defined by the library is an 'mp_int'.
However, it is not sufficient to simply declare a variable of type
mp_int in your program. These variables also need to be initialized
before they can be used, to allocate the internal storage they require
for computation.
This is done using one of the following functions:
mp_init(mp_int *mp);
mp_init_copy(mp_int *mp, mp_int *from);
mp_init_size(mp_int *mp, mp_size p);
Each of these requires a pointer to a structure of type mp_int. The
basic mp_init() simply initializes the mp_int to a default size, and
sets its value to zero. If you would like to initialize a copy of an
existing mp_int, use mp_init_copy(), where the 'from' parameter is the
mp_int you'd like to make a copy of. The third function,
mp_init_size(), permits you to specify how many digits of precision
should be preallocated for your mp_int. This can help the library
avoid unnecessary re-allocations later on.
The default precision used by mp_init() can be retrieved using:
precision = mp_get_prec();
This returns the number of digits that will be allocated. You can
change this value by using:
mp_set_prec(unsigned int prec);
Any positive value is acceptable -- if you pass zero, the default
precision will be re-set to the compiled-in library default (this is
specified in the header file 'mpi-config.h', and typically defaults to
8 or 16).
Just as you must allocate an mp_int before you can use it, you must
clean up the structure when you are done with it. This is performed
using the mp_clear() function. Remember that any mp_int that you
create as a local variable in a function must be mp_clear()'d before
that function exits, or else the memory allocated to that mp_int will
be orphaned and unrecoverable.
To set an mp_int to a given value, the following functions are given:
mp_set(mp_int *mp, mp_digit d);
mp_set_int(mp_int *mp, long z);
The mp_set() function sets the mp_int to a single digit value, while
mp_set_int() sets the mp_int to a signed long integer value.
To set an mp_int to zero, use:
mp_zero(mp_int *mp);
Copying and Moving
------------------
If you have two initialized mp_int's, and you want to copy the value
of one into the other, use:
mp_copy(from, to)
This takes care of clearing the old value of 'to', and copies the new
value into it. If 'to' is not yet initialized, use mp_init_copy()
instead (see above).
Note: The library tries, whenever possible, to avoid allocating
---- new memory. Thus, mp_copy() tries first to satisfy the needs
of the copy by re-using the memory already allocated to 'to'.
Only if this proves insufficient will mp_copy() actually
allocate new memory.
For this reason, if you know a priori that 'to' has enough
available space to hold 'from', you don't need to check the
return value of mp_copy() for memory failure. The USED()
macro tells you how many digits are used by an mp_int, and
the ALLOC() macro tells you how many are allocated.
If you have two initialized mp_int's, and you want to exchange their
values, use:
mp_exch(a, b)
This is better than using mp_copy() with a temporary, since it will
not (ever) touch the memory allocator -- it just swaps the exact
contents of the two structures. The mp_exch() function cannot fail;
if you pass it an invalid structure, it just ignores it, and does
nothing.
Basic Arithmetic
----------------
Once you have initialized your integers, you can operate on them. The
basic arithmetic functions on full mp_int values are:
mp_add(a, b, c) - computes c = a + b
mp_sub(a, b, c) - computes c = a - b
mp_mul(a, b, c) - computes c = a * b
mp_sqr(a, b) - computes b = a * a
mp_div(a, b, q, r) - computes q, r such that a = bq + r
mp_div_2d(a, d, q, r) - computes q = a / 2^d, r = a % 2^d
mp_expt(a, b, c) - computes c = a ** b
mp_2expt(a, k) - computes a = 2^k
mp_sqrt(a, c) - computes c = floor(sqrt(a))
The mp_div_2d() function efficiently computes division by powers of
two. Either the q or r parameter may be NULL, in which case that
portion of the computation will be discarded.
The algorithms used for some of the computations here are described in
the following files which are included with this distribution:
mul.txt Describes the multiplication algorithm
div.txt Describes the division algorithm
expt.txt Describes the exponentiation algorithm
sqrt.txt Describes the square-root algorithm
square.txt Describes the squaring algorithm
There are single-digit versions of most of these routines, as well.
In the following prototypes, 'd' is a single mp_digit:
mp_add_d(a, d, c) - computes c = a + d
mp_sub_d(a, d, c) - computes c = a - d
mp_mul_d(a, d, c) - computes c = a * d
mp_mul_2(a, c) - computes c = a * 2
mp_div_d(a, d, q, r) - computes q, r such that a = bq + r
mp_div_2(a, c) - computes c = a / 2
mp_expt_d(a, d, c) - computes c = a ** d
The mp_mul_2() and mp_div_2() functions take advantage of the internal
representation of an mp_int to do multiplication by two more quickly
than mp_mul_d() would. Other basic functions of an arithmetic variety
include:
mp_zero(a) - assign 0 to a
mp_neg(a, c) - negate a: c = -a
mp_abs(a, c) - absolute value: c = |a|
Comparisons
-----------
Several comparison functions are provided. Each of these, unless
otherwise specified, returns zero if the comparands are equal, < 0 if
the first is less than the second, and > 0 if the first is greater
than the second:
mp_cmp_z(a) - compare a <=> 0
mp_cmp_d(a, d) - compare a <=> d, d is a single digit
mp_cmp(a, b) - compare a <=> b
mp_cmp_mag(a, b) - compare |a| <=> |b|
mp_cmp_int(a, z) - compare a <=> z, z is a signed long integer
mp_isodd(a) - return nonzero if odd, zero otherwise
mp_iseven(a) - return nonzero if even, zero otherwise
Modular Arithmetic
------------------
Modular variations of the basic arithmetic functions are also
supported. These are available if the MP_MODARITH parameter in
mpi-config.h is turned on (it is by default). The modular arithmetic
functions are:
mp_mod(a, m, c) - compute c = a (mod m), 0 <= c < m
mp_mod_d(a, d, c) - compute c = a (mod d), 0 <= c < d (see below)
mp_addmod(a, b, m, c) - compute c = (a + b) mod m
mp_submod(a, b, m, c) - compute c = (a - b) mod m
mp_mulmod(a, b, m, c) - compute c = (a * b) mod m
mp_sqrmod(a, m, c) - compute c = (a * a) mod m
mp_exptmod(a, b, m, c) - compute c = (a ** b) mod m
mp_exptmod_d(a, d, m, c)- compute c = (a ** d) mod m
The mp_sqr() function squares its input argument. A call to mp_sqr(a,
c) is identical in meaning to mp_mul(a, a, c); however, if the
MP_SQUARE variable is set true in mpi-config.h (see below), then it
will be implemented with a different algorithm, that is supposed to
take advantage of the redundant computation that takes place during
squaring. Unfortunately, some compilers result in worse performance
on this code, so you can change the behaviour at will. There is a
utility program "mulsqr.c" that lets you test which does better on
your system.
The mp_sqrmod() function is analogous to the mp_sqr() function; it
uses the mp_sqr() function rather than mp_mul(), and then performs the
modular reduction. This probably won't help much unless you are doing
a lot of them.
See the file 'square.txt' for a synopsis of the algorithm used.
Note: The mp_mod_d() function computes a modular reduction around
---- a single digit d. The result is a single digit c.
Because an inverse is defined for a (mod m) if and only if (a, m) = 1
(that is, if a and m are relatively prime), mp_invmod() may not be
able to compute an inverse for the arguments. In this case, it
returns the value MP_UNDEF, and does not modify c. If an inverse is
defined, however, it returns MP_OKAY, and sets c to the value of the
inverse (mod m).
See the file 'redux.txt' for a description of the modular reduction
algorithm used by mp_exptmod().
Greatest Common Divisor
-----------------------
If The greates common divisor of two values can be found using one of the
following functions:
mp_gcd(a, b, c) - compute c = (a, b) using binary algorithm
mp_lcm(a, b, c) - compute c = [a, b] = ab / (a, b)
mp_xgcd(a, b, g, x, y) - compute g, x, y so that ax + by = g = (a, b)
Also provided is a function to compute modular inverses, if they
exist:
mp_invmod(a, m, c) - compute c = a^-1 (mod m), if it exists
The function mp_xgcd() computes the greatest common divisor, and also
returns values of x and y satisfying Bezout's identity. This is used
by mp_invmod() to find modular inverses. However, if you do not need
these values, you will find that mp_gcd() is MUCH more efficient,
since it doesn't need all the intermediate values that mp_xgcd()
requires in order to compute x and y.
The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD
algorithm due to Josef Stein.
Input & Output Functions
------------------------
The following basic I/O routines are provided. These are present at
all times:
mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int
mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int
mp_radix_size(mp, r) - return length of buffer needed by mp_toradix()
mp_raw_size(mp) - return length of buffer needed by mp_toraw()
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
digits
mp_toraw(mp, str) - convert an mp_int to a string of bytes
mp_tovalue(ch, r) - convert ch to its value when taken as
a radix r digit, or -1 if invalid
mp_strerror(err) - get a string describing mp_err value 'err'
If you compile the MPI library with MP_IOFUNC defined, you will also
have access to the following additional I/O function:
mp_print(mp, ofp) - print an mp_int as text to output stream ofp
Note that mp_radix_size() returns a size in bytes guaranteed to be AT
LEAST big enough for the digits output by mp_toradix(). Because it
uses an approximation technique to figure out how many digits will be
needed, it may return a figure which is larger than necessary. Thus,
the caller should not rely on the value to determine how many bytes
will actually be written by mp_toradix(). The string mp_toradix()
creates will be NUL terminated, so the standard C library function
strlen() should be able to ascertain this for you, if you need it.
The mp_read_radix() and mp_toradix() functions support bases from 2 to
64 inclusive. If you require more general radix conversion facilities
than this, you will need to write them yourself (that's why mp_div_d()
is provided, after all).
Note: mp_read_radix() will accept as digits either capital or
---- lower-case letters. However, the current implementation of
mp_toradix() only outputs upper-case letters, when writing
bases betwee 10 and 36. The underlying code supports using
lower-case letters, but the interface stub does not have a
selector for it. You can add one yourself if you think it
is worthwhile -- I do not. Bases from 36 to 64 use lower-
case letters as distinct from upper-case. Bases 63 and
64 use the characters '+' and '/' as digits.
Note also that compiling with MP_IOFUNC defined will cause
inclusion of <stdio.h>, so if you are trying to write code
which does not depend on the standard C library, you will
probably want to avoid this option. This is needed because
the mp_print() function takes a standard library FILE * as
one of its parameters, and uses the fprintf() function.
The mp_toraw() function converts the integer to a sequence of bytes,
in big-endian ordering (most-significant byte first). Assuming your
bytes are 8 bits wide, this corresponds to base 256. The sign is
encoded as a single leading byte, whose value is 0 for zero or
positive values, or 1 for negative values. The mp_read_raw() function
reverses this process -- it takes a buffer of bytes, interprets the
first as a sign indicator (0 = zero/positive, nonzero = negative), and
the rest as a sequence of 1-byte digits in big-endian ordering.
The mp_raw_size() function returns the exact number of bytes required
to store the given integer in "raw" format (as described in the
previous paragraph). Zero is returned in case of error; a valid
integer will require at least three bytes of storage.
In previous versions of the MPI library, an "external representation
format" was supported. This was removed, however, because I found I
was never using it, it was not as portable as I would have liked, and
I decided it was a waste of space.
Other Functions
---------------
The files 'mpprime.h' and 'mpprime.c' define some routines which are
useful for divisibility testing and probabilistic primality testing.
The routines defined are:
mpp_divis(a, b) - is a divisible by b?
mpp_divis_d(a, d) - is a divisible by digit d?
mpp_random(a) - set a to random value at current precision
mpp_random_size(a, prec) - set a to random value at given precision
Note: The mpp_random() and mpp_random_size() functions use the C
---- library's rand() function to generate random values. It is
up to the caller to seed this generator before it is called.
These functions are not suitable for generating quantities
requiring cryptographic-quality randomness; they are intended
primarily for use in primality testing.
Note too that the MPI library does not call srand(), so your
application should do this, if you ever want the sequence
to change.
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits
in v? If so, let w be the index of
that digit
mpp_divis_primes(a, np) - is a divisible by any of the first np
primes? If so, set np to the prime
which divided a.
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
returns MP_YES, otherwise MP_NO.
mpp_pprime(a, nt) - perform nt iterations of the Rabin-
Miller probabilistic primality test
on a. Returns MP_YES if all tests
passed, or MP_NO if any test fails.
The mpp_fermat() function works based on Fermat's little theorem, a
consequence of which is that if p is a prime, and (w, p) = 1, then:
w^p = w (mod p)
Put another way, if w^p != w (mod p), then p is not prime. The test
is expensive to compute, but it helps to quickly eliminate an enormous
class of composite numbers prior to Rabin-Miller testing.
Building the Library
--------------------
The MPI library is designed to be as self-contained as possible. You
should be able to compile it with your favourite ANSI C compiler, and
link it into your program directly. If you are on a Unix system using
the GNU C compiler (gcc), the following should work:
% gcc -ansi -pedantic -Wall -O2 -c mpi.c
The file 'mpi-config.h' defines several configurable parameters for
the library, which you can adjust to suit your application. At the
time of this writing, the available options are:
MP_IOFUNC - Define true to include the mp_print() function,
which is moderately useful for debugging. This
implicitly includes <stdio.h>.
MP_MODARITH - Define true to include the modular arithmetic
functions. If you don't need modular arithmetic
in your application, you can set this to zero to
leave out all the modular routines.
MP_NUMTH - Define true to include number theoretic functions
such as mp_gcd(), mp_lcm(), and mp_invmod().
MP_LOGTAB - If true, the file "logtab.h" is included, which
is basically a static table of base 2 logarithms.
These are used to compute how big the buffers for
radix conversion need to be. If you set this false,
the library includes <math.h> and uses log(). This
typically forces you to link against math libraries.
MP_MEMSET - If true, use memset() to zero buffers. If you run
into weird alignment related bugs, set this to zero
and an explicit loop will be used.
MP_MEMCPY - If true, use memcpy() to copy buffers. If you run
into weird alignment bugs, set this to zero and an
explicit loop will be used.
MP_CRYPTO - If true, whenever arrays of digits are free'd, they
are zeroed first. This is useful if you're using
the library in a cryptographic environment; however,
it does add overhead to each free operation. For
performance, if you don't care about zeroing your
buffers, set this to false.
MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument
checking macro, ARGCHK(), gets expanded. If this
is set to zero, ARGCHK() expands to nothing; no
argument checks are performed. If this is 1, the
ARGCHK() macro expands to code that returns MP_BADARG
or similar at runtime. If it is 2, ARGCHK() expands
to an assert() call that aborts the program on a
bad input.
MP_DEBUG - Turns on debugging output. This is probably not at
all useful unless you are debugging the library. It
tends to spit out a LOT of output.
MP_DEFPREC - The default precision of a newly-created mp_int, in
digits. The precision can be changed at runtime by
the mp_set_prec() function, but this is its initial
value.
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
function will use an alternate algorithm that takes
advantage of the redundant inner product computation
when both multiplicands are identical. Unfortunately,
with some compilers this is actually SLOWER than just
calling mp_mul() with the same argument twice. So
if you set MP_SQUARE to zero, mp_sqr() will be expan-
ded into a call to mp_mul(). This applies to all
the uses of mp_sqr(), including mp_sqrmod() and the
internal calls to s_mp_sqr() inside mpi.c
The program 'mulsqr' (mulsqr.c) can be used to test
which works best for your configuration. Set up the
CC and CFLAGS variables in the Makefile, then type:
make mulsqr
Invoke it with arguments similar to the following:
mulsqr 25000 1024
That is, 25000 products computed on 1024-bit values.
The output will compare the two timings, and recommend
a setting for MP_SQUARE. It is off by default.
If you would like to use the mp_print() function (see above), be sure
to define MP_IOFUNC in mpi-config.h. Many of the test drivers in the
'tests' subdirectory expect this to be defined (although the test
driver 'mpi-test' doesn't need it)
The Makefile which comes with the library should take care of building
the library for you, if you have set the CC and CFLAGS variables at
the top of the file appropriately. By default, they are set up to
use the GNU C compiler:
CC=gcc
CFLAGS=-ansi -pedantic -Wall -O2
If all goes well, the library should compile without warnings using
this combination. You should, of course, make whatever adjustments
you find necessary.
The MPI library distribution comes with several additional programs
which are intended to demonstrate the use of the library, and provide
a framework for testing it. There are a handful of test driver
programs, in the files named 'mptest-X.c', where X is a digit. Also,
there are some simple command-line utilities (in the 'utils'
directory) for manipulating large numbers. These include:
basecvt.c A radix-conversion program, supporting bases from
2 to 64 inclusive.
bbsrand.c A BBS (quadratic residue) pseudo-random number
generator. The file 'bbsrand.c' is just the driver
for the program; the real code lives in the files
'bbs_rand.h' and 'bbs_rand.c'
dec2hex.c Converts decimal to hexadecimal
gcd.c Computes the greatest common divisor of two values.
If invoked as 'xgcd', also computes constants x and
y such that (a, b) = ax + by, in accordance with
Bezout's identity.
hex2dec.c Converts hexadecimal to decimal
invmod.c Computes modular inverses
isprime.c Performs the Rabin-Miller probabilistic primality
test on a number. Values which fail this test are
definitely composite, and those which pass are very
likely to be prime (although there are no guarantees)
lap.c Computes the order (least annihilating power) of
a value v modulo m. Very dumb algorithm.
primegen.c Generates large (probable) primes.
prng.c A pseudo-random number generator based on the
BBS generator code in 'bbs_rand.c'
sieve.c Implements the Sieve of Eratosthenes, using a big
bitmap, to generate a list of prime numbers.
fact.c Computes the factorial of an arbitrary precision
integer (iterative).
exptmod.c Computes arbitrary precision modular exponentiation
from the command line (exptmod a b m -> a^b (mod m))
Most of these can be built from the Makefile that comes with the
library. Try 'make tools', if your environment supports it. (If you
are compiling on a Macintosh, I'm afraid you'll have to build them by
hand -- fortunately, this is not difficult -- the library itself
should compile just fine under Metrowerks CodeWarrior).
Testing the Library
-------------------
Automatic test vectors are included, in the form of a program called
'mpi-test'. To build this program and run all the tests, simply
invoke the shell script 'all-tests'. If all the tests pass, you
should see a message:
All tests passed
If something went wrong, you'll get:
One or more tests failed.
If this happens, scan back through the preceding lines, to see which
test failed. Any failure indicates a bug in the library, which needs
to be fixed before it will give accurate results. If you get any such
thing, please let me know, and I'll try to fix it. Please let me know
what platform and compiler you were using, as well as which test
failed. If a reason for failure was given, please send me that text
as well.
If you're on a system such as the Macintosh, where the standard Unix
build tools don't work, you can build the 'mpi-test' program manually,
and run it by hand. This is tedious and obnoxious, sorry.
Further manual testing can be performed by building the manual testing
programs, whose source is found in the 'tests' subdirectory. Each
test is in a source file called 'mptest-X.c'. The Makefile contains a
target to build all of them at once:
make tests
Read the comments at the top of each source file to see what the
driver is supposed to test. You probably don't need to do this; these
programs were only written to help me as I was developing the library.
The relevant files are:
mpi-test.c The source for the test driver
make-test-arrays A Perl script to generate some of the internal
data structures used by mpi-test.c
test-arrays.txt The source file for make-test-arrays
all-tests A Bourne shell script which runs all the
tests in the mpi-test suite
Running 'make mpi-test' should build the mpi-test program. If you
cannot use make, here is what needs to be done:
(1) Use 'make-test-arrays' to generate the file 'test-info.c' from
the 'test-arrays.txt' file. Since Perl can be found everywhere,
even on the Macintosh, this should be no trouble. Under Unix,
this looks like:
make-test-arrays test-arrays.txt > test-info.c
(2) Build the MPI library:
gcc -ansi -pedantic -Wall -c mpi.c
(3) Build the mpi-test program:
gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c
When you've got mpi-test, you can use 'all-tests' to run all the tests
made available by mpi-test. If any of them fail, there should be a
diagnostic indicating what went wrong. These are fairly high-level
diagnostics, and won't really help you debug the problem; they're
simply intended to help you isolate which function caused the problem.
If you encounter a problem of this sort, feel free to e-mail me, and I
will certainly attempt to help you debug it.
Note: Several of the tests hard-wired into 'mpi-test' operate under
---- the assumption that you are using at least a 16-bit mp_digit
type. If that is not true, several tests might fail, because
of range problems with the maximum digit value.
If you are using an 8-bit digit, you will also need to
modify the code for mp_read_raw(), which assumes that
multiplication by 256 can be done with mp_mul_d(), a
fact that fails when DIGIT_MAX is 255. You can replace
the call with s_mp_lshd(), which will give you the same
effect, and without doing as much work. :)
Acknowledgements:
----------------
The algorithms used in this library were drawn primarily from Volume
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
"Semi-Numerical Methods". Barrett's algorithm for modular reduction
came from Menezes, Oorschot, and Vanstone's _Handbook of Applied
Cryptography_, Chapter 14.
Thanks are due to Tom St. Denis, for finding an obnoxious sign-related
bug in mp_read_raw() that made things break on platforms which use
signed chars.
About the Author
----------------
This software was written by Michael J. Fromberger. You can contact
the author as follows:
E-mail: <sting@linguist.dartmouth.edu>
Postal: 8000 Cummings Hall, Thayer School of Engineering
Dartmouth College, Hanover, New Hampshire, USA
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907
Last updated: 16-Jan-2000

View File

@@ -1,115 +0,0 @@
#!/bin/sh
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
#
# The Initial Developer of the Original Code is
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
# Portions created by the Initial Developer are Copyright (C) 1997
# 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 *****
ECHO=/bin/echo
MAKE=gmake
$ECHO "\n** Running unit tests for MPI library\n"
# Build the mpi-test program, which comprises all the unit tests for
# the MPI library...
$ECHO "Bringing mpi-test up to date ... "
if $MAKE mpi-test ; then
:
else
$ECHO " "
$ECHO "Make failed to build mpi-test."
$ECHO " "
exit 1
fi
if [ ! -x mpi-test ] ; then
$ECHO " "
$ECHO "Cannot find 'mpi-test' program, testing cannot continue."
$ECHO " "
exit 1
fi
# Get the list of available test suites...
tests=`mpi-test list | awk '{print $1}'`
errs=0
# Run each test suite and check the result code of mpi-test
for test in $tests ; do
$ECHO "$test ... \c"
if mpi-test $test ; then
$ECHO "passed"
else
$ECHO "FAILED"
errs=1
fi
done
# If any tests failed, we'll stop at this point
if [ "$errs" = "0" ] ; then
$ECHO "All unit tests passed"
else
$ECHO "One or more tests failed"
exit 1
fi
# Now try to build the 'pi' program, and see if it can compute the
# first thousand digits of pi correctly
$ECHO "\n** Running other tests\n"
$ECHO "Bringing 'pi' up to date ... "
if $MAKE pi ; then
:
else
$ECHO "\nMake failed to build pi.\n"
exit 1
fi
if [ ! -x pi ] ; then
$ECHO "\nCannot find 'pi' program; testing cannot continue.\n"
exit 1
fi
./pi 2000 > /tmp/pi.tmp.$$
if cmp tests/pi2k.txt /tmp/pi.tmp.$$ ; then
$ECHO "Okay! The pi test passes."
else
$ECHO "Oops! The pi test failed. :("
exit 1
fi
rm -f /tmp/pi.tmp.$$
exit 0
# Here there be dragons

View File

@@ -1,11 +0,0 @@
Within this directory, each of the file listed below is licensed under
the terms given in the file LICENSE-MPL, also in this directory.
basecvt.pod
gcd.pod
invmod.pod
isprime.pod
lap.pod
mpi-test.pod
prime.txt
prng.pod

View File

@@ -1,32 +0,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/
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 Netscape are
Copyright (C) 1994-2000 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License Version 2 or later (the
"GPL"), in which case the provisions of the GPL are applicable
instead of those above. If you wish to allow use of your
version of this file only under the terms of the GPL and not to
allow others to use your version of this file under the MPL,
indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by
the GPL. If you do not delete the provisions above, a recipient
may use your version of this file under either the MPL or the
GPL.

View File

@@ -1,63 +0,0 @@
=head1 NAME
basecvt - radix conversion for arbitrary precision integers
=head1 SYNOPSIS
basecvt <ibase> <obase> [values]
=head1 DESCRIPTION
The B<basecvt> program is a command-line tool for converting integers
of arbitrary precision from one radix to another. The current version
supports radix values from 2 (binary) to 64, inclusive. The first two
command line arguments specify the input and output radix, in base 10.
Any further arguments are taken to be integers notated in the input
radix, and these are converted to the output radix. The output is
written, one integer per line, to standard output.
When reading integers, only digits considered "valid" for the input
radix are considered. Processing of an integer terminates when an
invalid input digit is encountered. So, for example, if you set the
input radix to 10 and enter '10ACF', B<basecvt> would assume that you
had entered '10' and ignore the rest of the string.
If no values are provided, no output is written, but the program
simply terminates with a zero exit status. Error diagnostics are
written to standard error in the event of out-of-range radix
specifications. Regardless of the actual values of the input and
output radix, the radix arguments are taken to be in base 10 (decimal)
notation.
=head1 DIGITS
For radices from 2-10, standard ASCII decimal digits 0-9 are used for
both input and output. For radices from 11-36, the ASCII letters A-Z
are also included, following the convention used in hexadecimal. In
this range, input is accepted in either upper or lower case, although
on output only lower-case letters are used.
For radices from 37-62, the output includes both upper- and lower-case
ASCII letters, and case matters. In this range, case is distinguished
both for input and for output values.
For radices 63 and 64, the characters '+' (plus) and '/' (forward
solidus) are also used. These are derived from the MIME base64
encoding scheme. The overall encoding is not the same as base64,
because the ASCII digits are used for the bottom of the range, and the
letters are shifted upward; however, the output will consist of the
same character set.
This input and output behaviour is inherited from the MPI library used
by B<basecvt>, and so is not configurable at runtime.
=head1 SEE ALSO
dec2hex(1), hex2dec(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:31 $

View File

@@ -1,66 +0,0 @@
#!/bin/sh
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
#
# 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
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Netscape Communications Corporation
#
# 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: build,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
#
VERS="1.7p6"
SECT="1"
NAME="MPI Tools"
echo "Building manual pages ..."
case $# in
0)
files=`ls *.pod`
;;
*)
files=$*
;;
esac
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
echo "Finished building."

View File

@@ -1,101 +0,0 @@
Division
This describes the division algorithm used by the MPI library.
Input: a, b; a > b
Compute: Q, R; a = Qb + R
The input numbers are normalized so that the high-order digit of b is
at least half the radix. This guarantees that we have a reasonable
way to guess at the digits of the quotient (this method was taken from
Knuth, vol. 2, with adaptations).
To normalize, test the high-order digit of b. If it is less than half
the radix, multiply both a and b by d, where:
radix - 1
d = -----------
bmax + 1
...where bmax is the high-order digit of b. Otherwise, set d = 1.
Given normalize values for a and b, let the notation a[n] denote the
nth digit of a. Let #a be the number of significant figures of a (not
including any leading zeroes).
Let R = 0
Let p = #a - 1
while(p >= 0)
do
R = (R * radix) + a[p]
p = p - 1
while(R < b and p >= 0)
if(R < b)
break
q = (R[#R - 1] * radix) + R[#R - 2]
q = q / b[#b - 1]
T = b * q
while(T > L)
q = q - 1
T = T - b
endwhile
L = L - T
Q = (Q * radix) + q
endwhile
At this point, Q is the quotient, and R is the normalized remainder.
To denormalize R, compute:
R = (R / d)
At this point, you are finished.
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: div.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,132 +0,0 @@
Exponentiation
For exponentiation, the MPI library uses a simple and fairly standard
square-and-multiply method. The algorithm is this:
Input: a, b
Output: a ** b
s = 1
while(b != 0)
if(b is odd)
s = s * a
endif
b = b / 2
x = x * x
endwhile
return s
The modular exponentiation is done the same way, except replacing:
s = s * a
with
s = (s * a) mod m
and replacing
x = x * x
with
x = (x * x) mod m
Here is a sample exponentiation using the MPI library, as compared to
the same problem solved by the Unix 'bc' program on my system:
Computation of 2,381,283 ** 235
'bc' says:
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
CFFF2E1AC93F3CA264A1B
MPI says:
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
CFFF2E1AC93F3CA264A1B
Diff says:
% diff bc.txt mp.txt
%
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: expt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,27 +0,0 @@
=head1 NAME
gcd - compute greatest common divisor of two integers
=head1 SYNOPSIS
gcd <a> <b>
=head1 DESCRIPTION
The B<gcd> program computes the greatest common divisor of two
arbitrary-precision integers I<a> and I<b>. The result is written in
standard decimal notation to the standard output.
If I<b> is zero, B<gcd> will print an error message and exit.
=head1 SEE ALSO
invmod(1), isprime(1), lap(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:32 $

View File

@@ -1,33 +0,0 @@
=head1 NAME
invmod - compute modular inverse of an integer
=head1 SYNOPSIS
invmod <a> <m>
=head1 DESCRIPTION
The B<invmod> program computes the inverse of I<a>, modulo I<m>, if
that inverse exists. Both I<a> and I<m> are arbitrary-precision
integers in decimal notation. The result is written in standard
decimal notation to the standard output.
If there is no inverse, the message:
No inverse
...will be printed to the standard output (an inverse exists if and
only if the greatest common divisor of I<a> and I<m> is 1).
=head1 SEE ALSO
gcd(1), isprime(1), lap(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:33 $

View File

@@ -1,62 +0,0 @@
=head1 NAME
isprime - probabilistic primality testing
=head1 SYNOPSIS
isprime <a>
=head1 DESCRIPTION
The B<isprime> program attempts to determine whether the arbitrary
precision integer I<a> is prime. It first tests I<a> for divisibility
by the first 170 or so small primes, and assuming I<a> is not
divisible by any of these, applies 15 iterations of the Rabin-Miller
probabilistic primality test.
If the program discovers that the number is composite, it will print:
Not prime (reason)
Where I<reason> is either:
divisible by small prime x
Or:
failed nth pseudoprime test
In the first case, I<x> indicates the first small prime factor that
was found. In the second case, I<n> indicates which of the
pseudoprime tests failed (numbered from 1)
If this happens, the number is definitely not prime. However, if the
number succeeds, this message results:
Probably prime, 1 in 4^15 chance of false positive
If this happens, the number is prime with very high probability, but
its primality has not been absolutely proven, only demonstrated to a
very convincing degree.
The value I<a> can be input in standard decimal notation, or, if it is
prefixed with I<Ox>, it will be read as hexadecimal.
=head1 ENVIRONMENT
You can control how many iterations of Rabin-Miller are performed on
the candidate number by setting the I<RM_TESTS> environment variable
to an integer value before starting up B<isprime>. This will change
the output slightly if the number passes all the tests.
=head1 SEE ALSO
gcd(1), invmod(1), lap(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:33 $

View File

@@ -1,35 +0,0 @@
=head1 NAME
lap - compute least annihilating power of a number
=head1 SYNOPSIS
lap <a> <m>
=head1 DESCRIPTION
The B<lap> program computes the order of I<a> modulo I<m>, for
arbitrary precision integers I<a> and I<m>. The B<order> of I<a>
modulo I<m> is defined as the smallest positive value I<n> for which
I<a> raised to the I<n>th power, modulo I<m>, is equal to 1. The
order may not exist, if I<m> is composite.
=head1 RESTRICTIONS
This program is very slow, especially for large moduli. It is
intended as a way to help find primitive elements in a modular field,
but it does not do so in a particularly inefficient manner. It was
written simply to help verify that a particular candidate does not
have an obviously short cycle mod I<m>.
=head1 SEE ALSO
gcd(1), invmod(1), isprime(1)
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:34 $

View File

@@ -1,49 +0,0 @@
=head1 NAME
mpi-test - automated test program for MPI library
=head1 SYNOPSIS
mpi-test <suite-name> [quiet]
mpi-test list
mpi-test help
=head1 DESCRIPTION
The B<mpi-test> program is a general unit test driver for the MPI
library. It is used to verify that the library works as it is
supposed to on your architecture. As with most such things, passing
all the tests in B<mpi-test> does not guarantee the code is correct,
but if any of them fail, there are certainly problems.
Each major function of the library can be tested individually. For a
list of the test suites understood by B<mpi-test>, run it with the
I<list> command line option:
mpi-test list
This will display a list of the available test suites and a brief
synopsis of what each one does. For a brief overview of this
document, run B<mpi-test> I<help>.
B<mpi-test> exits with a zero status if the selected test succeeds, or
a nonzero status if it fails. If a I<suite-name> which is not
understood by B<mpi-test> is given, a diagnostic is printed to the
standard error, and the program exits with a result code of 2. If a
test fails, the result code will be 1, and a diagnostic is ordinarily
printed to the standard error. However, if the I<quiet> option is
provided, these diagnostics will be suppressed.
=head1 RESTRICTIONS
Only a few canned test cases are provided. The solutions have been
verified using the GNU bc(1) program, so bugs there may cause problems
here; however, this is very unlikely, so if a test fails, it is almost
certainly my fault, not bc(1)'s.
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Thayer School of Engineering, Hanover, New Hampshire, USA
$Date: 2000-07-14 00:44:34 $

View File

@@ -1,114 +0,0 @@
Multiplication
This describes the multiplication algorithm used by the MPI library.
This is basically a standard "schoolbook" algorithm. It is slow --
O(mn) for m = #a, n = #b -- but easy to implement and verify.
Basically, we run two nested loops, as illustrated here (R is the
radix):
k = 0
for j <- 0 to (#b - 1)
for i <- 0 to (#a - 1)
w = (a[j] * b[i]) + k + c[i+j]
c[i+j] = w mod R
k = w div R
endfor
c[i+j] = k;
k = 0;
endfor
It is necessary that 'w' have room for at least two radix R digits.
The product of any two digits in radix R is at most:
(R - 1)(R - 1) = R^2 - 2R + 1
Since a two-digit radix-R number can hold R^2 - 1 distinct values,
this insures that the product will fit into the two-digit register.
To insure that two digits is enough for w, we must also show that
there is room for the carry-in from the previous multiplication, and
the current value of the product digit that is being recomputed.
Assuming each of these may be as big as R - 1 (and no larger,
certainly), two digits will be enough if and only if:
(R^2 - 2R + 1) + 2(R - 1) <= R^2 - 1
Solving this equation shows that, indeed, this is the case:
R^2 - 2R + 1 + 2R - 2 <= R^2 - 1
R^2 - 1 <= R^2 - 1
This suggests that a good radix would be one more than the largest
value that can be held in half a machine word -- so, for example, as
in this implementation, where we used a radix of 65536 on a machine
with 4-byte words. Another advantage of a radix of this sort is that
binary-level operations are easy on numbers in this representation.
Here's an example multiplication worked out longhand in radix-10,
using the above algorithm:
a = 999
b = x 999
-------------
p = 98001
w = (a[jx] * b[ix]) + kin + c[ix + jx]
c[ix+jx] = w % RADIX
k = w / RADIX
product
ix jx a[jx] b[ix] kin w c[i+j] kout 000000
0 0 9 9 0 81+0+0 1 8 000001
0 1 9 9 8 81+8+0 9 8 000091
0 2 9 9 8 81+8+0 9 8 000991
8 0 008991
1 0 9 9 0 81+0+9 0 9 008901
1 1 9 9 9 81+9+9 9 9 008901
1 2 9 9 9 81+9+8 8 9 008901
9 0 098901
2 0 9 9 0 81+0+9 0 9 098001
2 1 9 9 9 81+9+8 8 9 098001
2 2 9 9 9 81+9+9 9 9 098001
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: mul.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,90 +0,0 @@
This file describes how pi is computed by the program in 'pi.c' (see
the utils subdirectory).
Basically, we use Machin's formula, which is what everyone in the
world uses as a simple method for computing approximations to pi.
This works for up to a few thousand digits without too much effort.
Beyond that, though, it gets too slow.
Machin's formula states:
pi := 16 * arctan(1/5) - 4 * arctan(1/239)
We compute this in integer arithmetic by first multiplying everything
through by 10^d, where 'd' is the number of digits of pi we wanted to
compute. It turns out, the last few digits will be wrong, but the
number that are wrong is usually very small (ordinarly only 2-3).
Having done this, we compute the arctan() function using the formula:
1 1 1 1 1
arctan(1/x) := --- - ----- + ----- - ----- + ----- - ...
x 3 x^3 5 x^5 7 x^7 9 x^9
This is done iteratively by computing the first term manually, and
then iteratively dividing x^2 and k, where k = 3, 5, 7, ... out of the
current figure. This is then added to (or subtracted from) a running
sum, as appropriate. The iteration continues until we overflow our
available precision and the current figure goes to zero under integer
division. At that point, we're finished.
Actually, we get a couple extra bits of precision out of the fact that
we know we're computing y * arctan(1/x), by setting up the multiplier
as:
y * 10^d
... instead of just 10^d. There is also a bit of cleverness in how
the loop is constructed, to avoid special-casing the first term.
Check out the code for arctan() in 'pi.c', if you are interested in
seeing how it is set up.
Thanks to Jason P. for this algorithm, which I assembled from notes
and programs found on his cool "Pile of Pi Programs" page, at:
http://www.isr.umd.edu/~jasonp/pipage.html
Thanks also to Henrik Johansson <Henrik.Johansson@Nexus.Comm.SE>, from
whose pi program I borrowed the clever idea of pre-multiplying by x in
order to avoid a special case on the loop iteration.
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: pi.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

File diff suppressed because it is too large Load Diff

View File

@@ -1,41 +0,0 @@
=head1 NAME
prng - pseudo-random number generator
=head1 SYNOPSIS
prng [count]
=head1 DESCRIPTION
B<Prng> generates 32-bit pseudo-random integers using the
Blum-Blum-Shub (BBS) quadratic residue generator. It is seeded using
the standard C library's rand() function, which itself seeded from the
system clock and the process ID number. Thus, the values generated
are not particularly useful for cryptographic applications, but they
are in general much better than the typical output of the usual
multiplicative congruency generator used by most runtime libraries.
You may optionally specify how many random values should be generated
by giving a I<count> argument on the command line. If you do not
specify a count, only one random value will be generated. The results
are output to the standard output in decimal notation, one value per
line.
=head1 RESTRICTIONS
As stated above, B<prng> uses the C library's rand() function to seed
the generator, so it is not terribly suitable for cryptographic
applications. Also note that each time you run the program, a new
seed is generated, so it is better to run it once with a I<count>
parameter than it is to run it multiple times to generate several
values.
=head1 AUTHOR
Michael J. Fromberger <sting@linguist.dartmouth.edu>
Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
Thayer School of Engineering, Dartmouth College, Hanover, NH USA
$Date: 2000-07-14 00:44:36 $

View File

@@ -1,121 +0,0 @@
Modular Reduction
Usually, modular reduction is accomplished by long division, using the
mp_div() or mp_mod() functions. However, when performing modular
exponentiation, you spend a lot of time reducing by the same modulus
again and again. For this purpose, doing a full division for each
multiplication is quite inefficient.
For this reason, the mp_exptmod() function does not perform modular
reductions in the usual way, but instead takes advantage of an
algorithm due to Barrett, as described by Menezes, Oorschot and
VanStone in their book _Handbook of Applied Cryptography_, published
by the CRC Press (see Chapter 14 for details). This method reduces
most of the computation of reduction to efficient shifting and masking
operations, and avoids the multiple-precision division entirely.
Here is a brief synopsis of Barrett reduction, as it is implemented in
this library.
Let b denote the radix of the computation (one more than the maximum
value that can be denoted by an mp_digit). Let m be the modulus, and
let k be the number of significant digits of m. Let x be the value to
be reduced modulo m. By the Division Theorem, there exist unique
integers Q and R such that:
x = Qm + R, 0 <= R < m
Barrett reduction takes advantage of the fact that you can easily
approximate Q to within two, given a value M such that:
2k
b
M = floor( ----- )
m
Computation of M requires a full-precision division step, so if you
are only doing a single reduction by m, you gain no advantage.
However, when multiple reductions by the same m are required, this
division need only be done once, beforehand. Using this, we can use
the following equation to compute Q', an approximation of Q:
x
floor( ------ ) M
k-1
b
Q' = floor( ----------------- )
k+1
b
The divisions by b^(k-1) and b^(k+1) and the floor() functions can be
efficiently implemented with shifts and masks, leaving only a single
multiplication to be performed to get this approximation. It can be
shown that Q - 2 <= Q' <= Q, so in the worst case, we can get out with
two additional subtractions to bring the value into line with the
actual value of Q.
Once we've got Q', we basically multiply that by m and subtract from
x, yielding:
x - Q'm = Qm + R - Q'm
Since we know the constraint on Q', this is one of:
R
m + R
2m + R
Since R < m by the Division Theorem, we can simply subtract off m
until we get a value in the correct range, which will happen with no
more than 2 subtractions:
v = x - Q'm
while(v >= m)
v = v - m
endwhile
In random performance trials, modular exponentiation using this method
of reduction gave around a 40% speedup over using the division for
reduction.
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: redux.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,87 +0,0 @@
Square Root
A simple iterative algorithm is used to compute the greatest integer
less than or equal to the square root. Essentially, this is Newton's
linear approximation, computed by finding successive values of the
equation:
x[k]^2 - V
x[k+1] = x[k] - ------------
2 x[k]
...where V is the value for which the square root is being sought. In
essence, what is happening here is that we guess a value for the
square root, then figure out how far off we were by squaring our guess
and subtracting the target. Using this value, we compute a linear
approximation for the error, and adjust the "guess". We keep doing
this until the precision gets low enough that the above equation
yields a quotient of zero. At this point, our last guess is one
greater than the square root we're seeking.
The initial guess is computed by dividing V by 4, which is a heuristic
I have found to be fairly good on average. This also has the
advantage of being very easy to compute efficiently, even for large
values.
So, the resulting algorithm works as follows:
x = V / 4 /* compute initial guess */
loop
t = (x * x) - V /* Compute absolute error */
u = 2 * x /* Adjust by tangent slope */
t = t / u
/* Loop is done if error is zero */
if(t == 0)
break
/* Adjust guess by error term */
x = x - t
end
x = x - 1
The result of the computation is the value of x.
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: sqrt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,109 +0,0 @@
Squaring Algorithm
When you are squaring a value, you can take advantage of the fact that
half the multiplications performed by the more general multiplication
algorithm (see 'mul.txt' for a description) are redundant when the
multiplicand equals the multiplier.
In particular, the modified algorithm is:
k = 0
for j <- 0 to (#a - 1)
w = c[2*j] + (a[j] ^ 2);
k = w div R
for i <- j+1 to (#a - 1)
w = (2 * a[j] * a[i]) + k + c[i+j]
c[i+j] = w mod R
k = w div R
endfor
c[i+j] = k;
k = 0;
endfor
On the surface, this looks identical to the multiplication algorithm;
however, note the following differences:
- precomputation of the leading term in the outer loop
- i runs from j+1 instead of from zero
- doubling of a[i] * a[j] in the inner product
Unfortunately, the construction of the inner product is such that we
need more than two digits to represent the inner product, in some
cases. In a C implementation, this means that some gymnastics must be
performed in order to handle overflow, for which C has no direct
abstraction. We do this by observing the following:
If we have multiplied a[i] and a[j], and the product is more than half
the maximum value expressible in two digits, then doubling this result
will overflow into a third digit. If this occurs, we take note of the
overflow, and double it anyway -- C integer arithmetic ignores
overflow, so the two digits we get back should still be valid, modulo
the overflow.
Having doubled this value, we now have to add in the remainders and
the digits already computed by earlier steps. If we did not overflow
in the previous step, we might still cause an overflow here. That
will happen whenever the maximum value expressible in two digits, less
the amount we have to add, is greater than the result of the previous
step. Thus, the overflow computation is:
u = 0
w = a[i] * a[j]
if(w > (R - 1)/ 2)
u = 1;
w = w * 2
v = c[i + j] + k
if(u == 0 && (R - 1 - v) < w)
u = 1
If there is an overflow, u will be 1, otherwise u will be 0. The rest
of the parameters are the same as they are in the above description.
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: square.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,250 +0,0 @@
MPI Library Timing Tests
Hardware/OS
(A) SGI O2 1 x MIPS R10000 250MHz IRIX 6.5.3
(B) IBM RS/6000 43P-240 1 x PowerPC 603e 223MHz AIX 4.3
(C) Dell GX1/L+ 1 x Pentium III 550MHz Linux 2.2.12-20
(D) PowerBook G3 1 x PowerPC 750 266MHz LinuxPPC 2.2.6-15apmac
(E) PowerBook G3 1 x PowerPC 750 266MHz MacOS 8.5.1
(F) PowerBook G3 1 x PowerPC 750 400MHz MacOS 9.0.2
Compiler
(1) MIPSpro C 7.2.1 -O3 optimizations
(2) GCC 2.95.1 -O3 optimizations
(3) IBM AIX xlc -O3 optimizations (version unknown)
(4) EGCS 2.91.66 -O3 optimizations
(5) Metrowerks CodeWarrior 5.0 C, all optimizations
(6) MIPSpro C 7.30 -O3 optimizations
(7) same as (6), with optimized libmalloc.so
Timings are given in seconds, computed using the C library's clock()
function. The first column gives the hardware and compiler
configuration used for the test. The second column indicates the
number of tests that were aggregated to get the statistics for that
size. These were compiled using 16 bit digits.
Source data were generated randomly using a fixed seed, so they should
be internally consistent, but may vary on different systems depending
on the C library. Also, since the resolution of the timer accessed by
clock() varies, there may be some variance in the precision of these
measurements.
Prime Generation (primegen)
128 bits:
A1 200 min=0.03, avg=0.19, max=0.72, sum=38.46
A2 200 min=0.02, avg=0.16, max=0.62, sum=32.55
B3 200 min=0.01, avg=0.07, max=0.22, sum=13.29
C4 200 min=0.00, avg=0.03, max=0.20, sum=6.14
D4 200 min=0.00, avg=0.05, max=0.33, sum=9.70
A6 200 min=0.01, avg=0.09, max=0.36, sum=17.48
A7 200 min=0.00, avg=0.05, max=0.24, sum=10.07
192 bits:
A1 200 min=0.05, avg=0.45, max=3.13, sum=89.96
A2 200 min=0.04, avg=0.39, max=2.61, sum=77.55
B3 200 min=0.02, avg=0.18, max=1.25, sum=36.97
C4 200 min=0.01, avg=0.09, max=0.33, sum=18.24
D4 200 min=0.02, avg=0.15, max=0.54, sum=29.63
A6 200 min=0.02, avg=0.24, max=1.70, sum=47.84
A7 200 min=0.01, avg=0.15, max=1.05, sum=30.88
256 bits:
A1 200 min=0.08, avg=0.92, max=6.13, sum=184.79
A2 200 min=0.06, avg=0.76, max=5.03, sum=151.11
B3 200 min=0.04, avg=0.41, max=2.68, sum=82.35
C4 200 min=0.02, avg=0.19, max=0.69, sum=37.91
D4 200 min=0.03, avg=0.31, max=1.15, sum=63.00
A6 200 min=0.04, avg=0.48, max=3.13, sum=95.46
A7 200 min=0.03, avg=0.37, max=2.36, sum=73.60
320 bits:
A1 200 min=0.11, avg=1.59, max=6.14, sum=318.81
A2 200 min=0.09, avg=1.27, max=4.93, sum=254.03
B3 200 min=0.07, avg=0.82, max=3.13, sum=163.80
C4 200 min=0.04, avg=0.44, max=1.91, sum=87.59
D4 200 min=0.06, avg=0.73, max=3.22, sum=146.73
A6 200 min=0.07, avg=0.93, max=3.50, sum=185.01
A7 200 min=0.05, avg=0.76, max=2.94, sum=151.78
384 bits:
A1 200 min=0.16, avg=2.69, max=11.41, sum=537.89
A2 200 min=0.13, avg=2.15, max=9.03, sum=429.14
B3 200 min=0.11, avg=1.54, max=6.49, sum=307.78
C4 200 min=0.06, avg=0.81, max=4.84, sum=161.13
D4 200 min=0.10, avg=1.38, max=8.31, sum=276.81
A6 200 min=0.11, avg=1.73, max=7.36, sum=345.55
A7 200 min=0.09, avg=1.46, max=6.12, sum=292.02
448 bits:
A1 200 min=0.23, avg=3.36, max=15.92, sum=672.63
A2 200 min=0.17, avg=2.61, max=12.25, sum=522.86
B3 200 min=0.16, avg=2.10, max=9.83, sum=420.86
C4 200 min=0.09, avg=1.44, max=7.64, sum=288.36
D4 200 min=0.16, avg=2.50, max=13.29, sum=500.17
A6 200 min=0.15, avg=2.31, max=10.81, sum=461.58
A7 200 min=0.14, avg=2.03, max=9.53, sum=405.16
512 bits:
A1 200 min=0.30, avg=6.12, max=22.18, sum=1223.35
A2 200 min=0.25, avg=4.67, max=16.90, sum=933.18
B3 200 min=0.23, avg=4.13, max=14.94, sum=825.45
C4 200 min=0.13, avg=2.08, max=9.75, sum=415.22
D4 200 min=0.24, avg=4.04, max=20.18, sum=808.11
A6 200 min=0.22, avg=4.47, max=16.19, sum=893.83
A7 200 min=0.20, avg=4.03, max=14.65, sum=806.02
Modular Exponentation (metime)
The following results are aggregated from 200 pseudo-randomly
generated tests, based on a fixed seed.
base, exponent, and modulus size (bits)
P/C 128 192 256 320 384 448 512 640 768 896 1024
------- -----------------------------------------------------------------
A1 0.015 0.027 0.047 0.069 0.098 0.133 0.176 0.294 0.458 0.680 1.040
A2 0.013 0.024 0.037 0.053 0.077 0.102 0.133 0.214 0.326 0.476 0.668
B3 0.005 0.011 0.021 0.036 0.056 0.084 0.121 0.222 0.370 0.573 0.840
C4 0.002 0.006 0.011 0.020 0.032 0.048 0.069 0.129 0.223 0.344 0.507
D4 0.004 0.010 0.019 0.034 0.056 0.085 0.123 0.232 0.390 0.609 0.899
E5 0.007 0.015 0.031 0.055 0.088 0.133 0.183 0.342 0.574 0.893 1.317
A6 0.008 0.016 0.038 0.042 0.064 0.093 0.133 0.239 0.393 0.604 0.880
A7 0.005 0.011 0.020 0.036 0.056 0.083 0.121 0.223 0.374 0.583 0.855
Multiplication and Squaring tests, (mulsqr)
The following results are aggregated from 500000 pseudo-randomly
generated tests, based on a per-run wall-clock seed. Times are given
in seconds, except where indicated in microseconds (us).
(A1)
bits multiply square ad percent time/mult time/square
64 9.33 9.15 > 1.9 18.7us 18.3us
128 10.88 10.44 > 4.0 21.8us 20.9us
192 13.30 11.89 > 10.6 26.7us 23.8us
256 14.88 12.64 > 15.1 29.8us 25.3us
320 18.64 15.01 > 19.5 37.3us 30.0us
384 23.11 17.70 > 23.4 46.2us 35.4us
448 28.28 20.88 > 26.2 56.6us 41.8us
512 34.09 24.51 > 28.1 68.2us 49.0us
640 47.86 33.25 > 30.5 95.7us 66.5us
768 64.91 43.54 > 32.9 129.8us 87.1us
896 84.49 55.48 > 34.3 169.0us 111.0us
1024 107.25 69.21 > 35.5 214.5us 138.4us
1536 227.97 141.91 > 37.8 456.0us 283.8us
2048 394.05 242.15 > 38.5 788.1us 484.3us
(A2)
bits multiply square ad percent time/mult time/square
64 7.87 7.95 < 1.0 15.7us 15.9us
128 9.40 9.19 > 2.2 18.8us 18.4us
192 11.15 10.59 > 5.0 22.3us 21.2us
256 12.02 11.16 > 7.2 24.0us 22.3us
320 14.62 13.43 > 8.1 29.2us 26.9us
384 17.72 15.80 > 10.8 35.4us 31.6us
448 21.24 18.51 > 12.9 42.5us 37.0us
512 25.36 21.78 > 14.1 50.7us 43.6us
640 34.57 29.00 > 16.1 69.1us 58.0us
768 46.10 37.60 > 18.4 92.2us 75.2us
896 58.94 47.72 > 19.0 117.9us 95.4us
1024 73.76 59.12 > 19.8 147.5us 118.2us
1536 152.00 118.80 > 21.8 304.0us 237.6us
2048 259.41 199.57 > 23.1 518.8us 399.1us
(B3)
bits multiply square ad percent time/mult time/square
64 2.60 2.47 > 5.0 5.20us 4.94us
128 4.43 4.06 > 8.4 8.86us 8.12us
192 7.03 6.10 > 13.2 14.1us 12.2us
256 10.44 8.59 > 17.7 20.9us 17.2us
320 14.44 11.64 > 19.4 28.9us 23.3us
384 19.12 15.08 > 21.1 38.2us 30.2us
448 24.55 19.09 > 22.2 49.1us 38.2us
512 31.03 23.53 > 24.2 62.1us 47.1us
640 45.05 33.80 > 25.0 90.1us 67.6us
768 63.02 46.05 > 26.9 126.0us 92.1us
896 83.74 60.29 > 28.0 167.5us 120.6us
1024 106.73 76.65 > 28.2 213.5us 153.3us
1536 228.94 160.98 > 29.7 457.9us 322.0us
2048 398.08 275.93 > 30.7 796.2us 551.9us
(C4)
bits multiply square ad percent time/mult time/square
64 1.34 1.28 > 4.5 2.68us 2.56us
128 2.76 2.59 > 6.2 5.52us 5.18us
192 4.52 4.16 > 8.0 9.04us 8.32us
256 6.64 5.99 > 9.8 13.3us 12.0us
320 9.20 8.13 > 11.6 18.4us 16.3us
384 12.01 10.58 > 11.9 24.0us 21.2us
448 15.24 13.33 > 12.5 30.5us 26.7us
512 19.02 16.46 > 13.5 38.0us 32.9us
640 27.56 23.54 > 14.6 55.1us 47.1us
768 37.89 31.78 > 16.1 75.8us 63.6us
896 49.24 41.42 > 15.9 98.5us 82.8us
1024 62.59 52.18 > 16.6 125.2us 104.3us
1536 131.66 107.72 > 18.2 263.3us 215.4us
2048 226.45 182.95 > 19.2 453.0us 365.9us
(A7)
bits multiply square ad percent time/mult time/square
64 1.74 1.71 > 1.7 3.48us 3.42us
128 3.48 2.96 > 14.9 6.96us 5.92us
192 5.74 4.60 > 19.9 11.5us 9.20us
256 8.75 6.61 > 24.5 17.5us 13.2us
320 12.5 8.99 > 28.1 25.0us 18.0us
384 16.9 11.9 > 29.6 33.8us 23.8us
448 22.2 15.2 > 31.7 44.4us 30.4us
512 28.3 19.0 > 32.7 56.6us 38.0us
640 42.4 28.0 > 34.0 84.8us 56.0us
768 59.4 38.5 > 35.2 118.8us 77.0us
896 79.5 51.2 > 35.6 159.0us 102.4us
1024 102.6 65.5 > 36.2 205.2us 131.0us
1536 224.3 140.6 > 37.3 448.6us 281.2us
2048 393.4 244.3 > 37.9 786.8us 488.6us
------------------------------------------------------------------
***** 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 MPI Arbitrary Precision Integer Arithmetic
library.
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, 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: timing.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $

View File

@@ -1,640 +0,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/
*
* 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 multacc512 multiple-precision integer arithmetic.
*
* The Initial Developer of the Original Code is Hewlett-Packard Company.
* Portions created by Hewlett-Packard Company are
* Copyright (C) March 1999, Hewlett-Packard Company. All Rights Reserved.
*
* Contributor(s):
* coded by: Bill Worley, Hewlett-Packard labs
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*
* This PA-RISC 2.0 function computes the product of two unsigned integers,
* and adds the result to a previously computed integer. The multiplicand
* is a 512-bit (64-byte, eight doubleword) unsigned integer, stored in
* memory in little-double-wordian order. The multiplier is an unsigned
* 64-bit integer. The previously computed integer to which the product is
* added is located in the result ("res") area, and is assumed to be a
* 576-bit (72-byte, nine doubleword) unsigned integer, stored in memory
* in little-double-wordian order. This value normally will be the result
* of a previously computed nine doubleword result. It is not necessary
* to pad the multiplicand with an additional 64-bit zero doubleword.
*
* Multiplicand, multiplier, and addend ideally should be aligned at
* 16-byte boundaries for best performance. The code will function
* correctly for alignment at eight-byte boundaries which are not 16-byte
* boundaries, but the execution may be slightly slower due to even/odd
* bank conflicts on PA-RISC 8000 processors.
*
* This function is designed to accept the same calling sequence as Bill
* Ackerman's "maxpy_little" function. The carry from the ninth doubleword
* of the result is written to the tenth word of the result, as is done by
* Bill Ackerman's function. The final carry also is returned as an
* integer, which may be ignored. The function prototype may be either
* of the following:
*
* void multacc512( int l, chunk* m, const chunk* a, chunk* res );
* or
* int multacc512( int l, chunk* m, const chunk* a, chunk* res );
*
* where: "l" originally denoted vector lengths. This parameter is
* ignored. This function always assumes a multiplicand length of
* 512 bits (eight doublewords), and addend and result lengths of
* 576 bits (nine doublewords).
*
* "m" is a pointer to the doubleword multiplier, ideally aligned
* on a 16-byte boundary.
*
* "a" is a pointer to the eight-doubleword multiplicand, stored
* in little-double-wordian order, and ideally aligned on a 16-byte
* boundary.
*
* "res" is a pointer to the nine doubleword addend, and to the
* nine-doubleword product computed by this function. The result
* also is stored in little-double-wordian order, and ideally is
* aligned on a 16-byte boundary. It is expected that the alignment
* of the "res" area may alternate between even/odd doubleword
* boundaries for successive calls for 512-bit x 512-bit
* multiplications.
*
* The code for this function has been scheduled to use the parallelism
* of the PA-RISC 8000 series microprocessors as well as the author was
* able. Comments and/or suggestions for improvement are welcomed.
*
* The code is "64-bit safe". This means it may be called in either
* the 32ILP context or the 64LP context. All 64-bits of registers are
* saved and restored.
*
* This code is self-contained. It requires no other header files in order
* to compile and to be linkable on a PA-RISC 2.0 machine. Symbolic
* definitions for registers and stack offsets are included within this
* one source file.
*
* This is a leaf routine. As such, minimal use is made of the stack area.
* Of the 192 bytes allocated, 64 bytes are used for saving/restoring eight
* general registers, and 128 bytes are used to move intermediate products
* from the floating-point registers to the general registers. Stack
* protocols assure proper alignment of these areas.
*
*/
/* ====================================================================*/
/* symbolic definitions for PA-RISC registers */
/* in the MIPS style, avoids lots of case shifts */
/* assigments (except t4) preserve register number parity */
/* ====================================================================*/
#define zero %r0 /* permanent zero */
#define t5 %r1 /* temp register, altered by addil */
#define rp %r2 /* return pointer */
#define s1 %r3 /* callee saves register*/
#define s0 %r4 /* callee saves register*/
#define s3 %r5 /* callee saves register*/
#define s2 %r6 /* callee saves register*/
#define s5 %r7 /* callee saves register*/
#define s4 %r8 /* callee saves register*/
#define s7 %r9 /* callee saves register*/
#define s6 %r10 /* callee saves register*/
#define t1 %r19 /* caller saves register*/
#define t0 %r20 /* caller saves register*/
#define t3 %r21 /* caller saves register*/
#define t2 %r22 /* caller saves register*/
#define a3 %r23 /* fourth argument register, high word */
#define a2 %r24 /* third argument register, low word*/
#define a1 %r25 /* second argument register, high word*/
#define a0 %r26 /* first argument register, low word*/
#define v0 %r28 /* high order return value*/
#define v1 %r29 /* low order return value*/
#define sp %r30 /* stack pointer*/
#define t4 %r31 /* temporary register */
#define fa0 %fr4 /* first argument register*/
#define fa1 %fr5 /* second argument register*/
#define fa2 %fr6 /* third argument register*/
#define fa3 %fr7 /* fourth argument register*/
#define fa0r %fr4R /* first argument register*/
#define fa1r %fr5R /* second argument register*/
#define fa2r %fr6R /* third argument register*/
#define fa3r %fr7R /* fourth argument register*/
#define ft0 %fr8 /* caller saves register*/
#define ft1 %fr9 /* caller saves register*/
#define ft2 %fr10 /* caller saves register*/
#define ft3 %fr11 /* caller saves register*/
#define ft0r %fr8R /* caller saves register*/
#define ft1r %fr9R /* caller saves register*/
#define ft2r %fr10R /* caller saves register*/
#define ft3r %fr11R /* caller saves register*/
#define ft4 %fr22 /* caller saves register*/
#define ft5 %fr23 /* caller saves register*/
#define ft6 %fr24 /* caller saves register*/
#define ft7 %fr25 /* caller saves register*/
#define ft8 %fr26 /* caller saves register*/
#define ft9 %fr27 /* caller saves register*/
#define ft10 %fr28 /* caller saves register*/
#define ft11 %fr29 /* caller saves register*/
#define ft12 %fr30 /* caller saves register*/
#define ft13 %fr31 /* caller saves register*/
#define ft4r %fr22R /* caller saves register*/
#define ft5r %fr23R /* caller saves register*/
#define ft6r %fr24R /* caller saves register*/
#define ft7r %fr25R /* caller saves register*/
#define ft8r %fr26R /* caller saves register*/
#define ft9r %fr27R /* caller saves register*/
#define ft10r %fr28R /* caller saves register*/
#define ft11r %fr29R /* caller saves register*/
#define ft12r %fr30R /* caller saves register*/
#define ft13r %fr31R /* caller saves register*/
/* ================================================================== */
/* functional definitions for PA-RISC registers */
/* ================================================================== */
/* general registers */
#define T1 a0 /* temp, (length parameter ignored) */
#define pM a1 /* -> 64-bit multiplier */
#define T2 a1 /* temp, (after fetching multiplier) */
#define pA a2 /* -> multiplicand vector (8 64-bit words) */
#define T3 a2 /* temp, (after fetching multiplicand) */
#define pR a3 /* -> addend vector (8 64-bit doublewords,
result vector (9 64-bit words) */
#define S0 s0 /* callee saves summand registers */
#define S1 s1
#define S2 s2
#define S3 s3
#define S4 s4
#define S5 s5
#define S6 s6
#define S7 s7
#define S8 v0 /* caller saves summand registers */
#define S9 v1
#define S10 t0
#define S11 t1
#define S12 t2
#define S13 t3
#define S14 t4
#define S15 t5
/* floating-point registers */
#define M fa0 /* multiplier double word */
#define MR fa0r /* low order half of multiplier double word */
#define ML fa0 /* high order half of multiplier double word */
#define A0 fa2 /* multiplicand double word 0 */
#define A0R fa2r /* low order half of multiplicand double word */
#define A0L fa2 /* high order half of multiplicand double word */
#define A1 fa3 /* multiplicand double word 1 */
#define A1R fa3r /* low order half of multiplicand double word */
#define A1L fa3 /* high order half of multiplicand double word */
#define A2 ft0 /* multiplicand double word 2 */
#define A2R ft0r /* low order half of multiplicand double word */
#define A2L ft0 /* high order half of multiplicand double word */
#define A3 ft1 /* multiplicand double word 3 */
#define A3R ft1r /* low order half of multiplicand double word */
#define A3L ft1 /* high order half of multiplicand double word */
#define A4 ft2 /* multiplicand double word 4 */
#define A4R ft2r /* low order half of multiplicand double word */
#define A4L ft2 /* high order half of multiplicand double word */
#define A5 ft3 /* multiplicand double word 5 */
#define A5R ft3r /* low order half of multiplicand double word */
#define A5L ft3 /* high order half of multiplicand double word */
#define A6 ft4 /* multiplicand double word 6 */
#define A6R ft4r /* low order half of multiplicand double word */
#define A6L ft4 /* high order half of multiplicand double word */
#define A7 ft5 /* multiplicand double word 7 */
#define A7R ft5r /* low order half of multiplicand double word */
#define A7L ft5 /* high order half of multiplicand double word */
#define P0 ft6 /* product word 0 */
#define P1 ft7 /* product word 0 */
#define P2 ft8 /* product word 0 */
#define P3 ft9 /* product word 0 */
#define P4 ft10 /* product word 0 */
#define P5 ft11 /* product word 0 */
#define P6 ft12 /* product word 0 */
#define P7 ft13 /* product word 0 */
/* ====================================================================== */
/* symbolic definitions for HP-UX stack offsets */
/* symbolic definitions for memory NOPs */
/* ====================================================================== */
#define ST_SZ 192 /* stack area total size */
#define SV0 -192(sp) /* general register save area */
#define SV1 -184(sp)
#define SV2 -176(sp)
#define SV3 -168(sp)
#define SV4 -160(sp)
#define SV5 -152(sp)
#define SV6 -144(sp)
#define SV7 -136(sp)
#define XF0 -128(sp) /* data transfer area */
#define XF1 -120(sp) /* for floating-pt to integer regs */
#define XF2 -112(sp)
#define XF3 -104(sp)
#define XF4 -96(sp)
#define XF5 -88(sp)
#define XF6 -80(sp)
#define XF7 -72(sp)
#define XF8 -64(sp)
#define XF9 -56(sp)
#define XF10 -48(sp)
#define XF11 -40(sp)
#define XF12 -32(sp)
#define XF13 -24(sp)
#define XF14 -16(sp)
#define XF15 -8(sp)
#define mnop proberi (sp),3,zero /* memory NOP */
/* ====================================================================== */
/* assembler formalities */
/* ====================================================================== */
#ifdef __LP64__
.level 2.0W
#else
.level 2.0
#endif
.space $TEXT$
.subspa $CODE$
.align 16
/* ====================================================================== */
/* here to compute 64-bit x 512-bit product + 512-bit addend */
/* ====================================================================== */
multacc512
.PROC
.CALLINFO
.ENTER
fldd 0(pM),M ; multiplier double word
ldo ST_SZ(sp),sp ; push stack
fldd 0(pA),A0 ; multiplicand double word 0
std S1,SV1 ; save s1
fldd 16(pA),A2 ; multiplicand double word 2
std S3,SV3 ; save s3
fldd 32(pA),A4 ; multiplicand double word 4
std S5,SV5 ; save s5
fldd 48(pA),A6 ; multiplicand double word 6
std S7,SV7 ; save s7
std S0,SV0 ; save s0
fldd 8(pA),A1 ; multiplicand double word 1
xmpyu MR,A0L,P0 ; A0 cross 32-bit word products
xmpyu ML,A0R,P2
std S2,SV2 ; save s2
fldd 24(pA),A3 ; multiplicand double word 3
xmpyu MR,A2L,P4 ; A2 cross 32-bit word products
xmpyu ML,A2R,P6
std S4,SV4 ; save s4
fldd 40(pA),A5 ; multiplicand double word 5
std S6,SV6 ; save s6
fldd 56(pA),A7 ; multiplicand double word 7
fstd P0,XF0 ; MR * A0L
xmpyu MR,A0R,P0 ; A0 right 32-bit word product
xmpyu MR,A1L,P1 ; A1 cross 32-bit word product
fstd P2,XF2 ; ML * A0R
xmpyu ML,A0L,P2 ; A0 left 32-bit word product
xmpyu ML,A1R,P3 ; A1 cross 32-bit word product
fstd P4,XF4 ; MR * A2L
xmpyu MR,A2R,P4 ; A2 right 32-bit word product
xmpyu MR,A3L,P5 ; A3 cross 32-bit word product
fstd P6,XF6 ; ML * A2R
xmpyu ML,A2L,P6 ; A2 parallel 32-bit word product
xmpyu ML,A3R,P7 ; A3 cross 32-bit word product
ldd XF0,S0 ; MR * A0L
fstd P1,XF1 ; MR * A1L
ldd XF2,S2 ; ML * A0R
fstd P3,XF3 ; ML * A1R
ldd XF4,S4 ; MR * A2L
fstd P5,XF5 ; MR * A3L
xmpyu MR,A1R,P1 ; A1 parallel 32-bit word products
xmpyu ML,A1L,P3
ldd XF6,S6 ; ML * A2R
fstd P7,XF7 ; ML * A3R
xmpyu MR,A3R,P5 ; A3 parallel 32-bit word products
xmpyu ML,A3L,P7
fstd P0,XF0 ; MR * A0R
ldd XF1,S1 ; MR * A1L
nop
add S0,S2,T1 ; A0 cross product sum
fstd P2,XF2 ; ML * A0L
ldd XF3,S3 ; ML * A1R
add,dc zero,zero,S0 ; A0 cross product sum carry
depd,z T1,31,32,S2 ; A0 cross product sum << 32
fstd P4,XF4 ; MR * A2R
ldd XF5,S5 ; MR * A3L
shrpd S0,T1,32,S0 ; A0 carry | cross product sum >> 32
add S4,S6,T3 ; A2 cross product sum
fstd P6,XF6 ; ML * A2L
ldd XF7,S7 ; ML * A3R
add,dc zero,zero,S4 ; A2 cross product sum carry
depd,z T3,31,32,S6 ; A2 cross product sum << 32
ldd XF0,S8 ; MR * A0R
fstd P1,XF1 ; MR * A1R
xmpyu MR,A4L,P0 ; A4 cross 32-bit word product
xmpyu MR,A5L,P1 ; A5 cross 32-bit word product
ldd XF2,S10 ; ML * A0L
fstd P3,XF3 ; ML * A1L
xmpyu ML,A4R,P2 ; A4 cross 32-bit word product
xmpyu ML,A5R,P3 ; A5 cross 32-bit word product
ldd XF4,S12 ; MR * A2R
fstd P5,XF5 ; MR * A3L
xmpyu MR,A6L,P4 ; A6 cross 32-bit word product
xmpyu MR,A7L,P5 ; A7 cross 32-bit word product
ldd XF6,S14 ; ML * A2L
fstd P7,XF7 ; ML * A3L
xmpyu ML,A6R,P6 ; A6 cross 32-bit word product
xmpyu ML,A7R,P7 ; A7 cross 32-bit word product
fstd P0,XF0 ; MR * A4L
ldd XF1,S9 ; MR * A1R
shrpd S4,T3,32,S4 ; A2 carry | cross product sum >> 32
add S1,S3,T1 ; A1 cross product sum
fstd P2,XF2 ; ML * A4R
ldd XF3,S11 ; ML * A1L
add,dc zero,zero,S1 ; A1 cross product sum carry
depd,z T1,31,32,S3 ; A1 cross product sum << 32
fstd P4,XF4 ; MR * A6L
ldd XF5,S13 ; MR * A3R
shrpd S1,T1,32,S1 ; A1 carry | cross product sum >> 32
add S5,S7,T3 ; A3 cross product sum
fstd P6,XF6 ; ML * A6R
ldd XF7,S15 ; ML * A3L
add,dc zero,zero,S5 ; A3 cross product sum carry
depd,z T3,31,32,S7 ; A3 cross product sum << 32
shrpd S5,T3,32,S5 ; A3 carry | cross product sum >> 32
add S2,S8,S8 ; M * A0 right doubleword, P0 doubleword
add,dc S0,S10,S10 ; M * A0 left doubleword
add S3,S9,S9 ; M * A1 right doubleword
add,dc S1,S11,S11 ; M * A1 left doubleword
add S6,S12,S12 ; M * A2 right doubleword
ldd 24(pR),S3 ; Addend word 3
fstd P1,XF1 ; MR * A5L
add,dc S4,S14,S14 ; M * A2 left doubleword
xmpyu MR,A5R,P1 ; A5 right 32-bit word product
ldd 8(pR),S1 ; Addend word 1
fstd P3,XF3 ; ML * A5R
add S7,S13,S13 ; M * A3 right doubleword
xmpyu ML,A5L,P3 ; A5 left 32-bit word product
ldd 0(pR),S7 ; Addend word 0
fstd P5,XF5 ; MR * A7L
add,dc S5,S15,S15 ; M * A3 left doubleword
xmpyu MR,A7R,P5 ; A7 right 32-bit word product
ldd 16(pR),S5 ; Addend word 2
fstd P7,XF7 ; ML * A7R
add S10,S9,S9 ; P1 doubleword
xmpyu ML,A7L,P7 ; A7 left 32-bit word products
ldd XF0,S0 ; MR * A4L
fstd P1,XF9 ; MR * A5R
add,dc S11,S12,S12 ; P2 doubleword
xmpyu MR,A4R,P0 ; A4 right 32-bit word product
ldd XF2,S2 ; ML * A4R
fstd P3,XF11 ; ML * A5L
add,dc S14,S13,S13 ; P3 doubleword
xmpyu ML,A4L,P2 ; A4 left 32-bit word product
ldd XF6,S6 ; ML * A6R
fstd P5,XF13 ; MR * A7R
add,dc zero,S15,T2 ; P4 partial doubleword
xmpyu MR,A6R,P4 ; A6 right 32-bit word product
ldd XF4,S4 ; MR * A6L
fstd P7,XF15 ; ML * A7L
add S7,S8,S8 ; R0 + P0, new R0 doubleword
xmpyu ML,A6L,P6 ; A6 left 32-bit word product
fstd P0,XF0 ; MR * A4R
ldd XF7,S7 ; ML * A7R
add,dc S1,S9,S9 ; c + R1 + P1, new R1 doubleword
fstd P2,XF2 ; ML * A4L
ldd XF1,S1 ; MR * A5L
add,dc S5,S12,S12 ; c + R2 + P2, new R2 doubleword
fstd P4,XF4 ; MR * A6R
ldd XF5,S5 ; MR * A7L
add,dc S3,S13,S13 ; c + R3 + P3, new R3 doubleword
fstd P6,XF6 ; ML * A6L
ldd XF3,S3 ; ML * A5R
add,dc zero,T2,T2 ; c + partial P4
add S0,S2,T1 ; A4 cross product sum
std S8,0(pR) ; save R0
add,dc zero,zero,S0 ; A4 cross product sum carry
depd,z T1,31,32,S2 ; A4 cross product sum << 32
std S9,8(pR) ; save R1
shrpd S0,T1,32,S0 ; A4 carry | cross product sum >> 32
add S4,S6,T3 ; A6 cross product sum
std S12,16(pR) ; save R2
add,dc zero,zero,S4 ; A6 cross product sum carry
depd,z T3,31,32,S6 ; A6 cross product sum << 32
std S13,24(pR) ; save R3
shrpd S4,T3,32,S4 ; A6 carry | cross product sum >> 32
add S1,S3,T1 ; A5 cross product sum
ldd XF0,S8 ; MR * A4R
add,dc zero,zero,S1 ; A5 cross product sum carry
depd,z T1,31,32,S3 ; A5 cross product sum << 32
ldd XF2,S10 ; ML * A4L
ldd XF9,S9 ; MR * A5R
shrpd S1,T1,32,S1 ; A5 carry | cross product sum >> 32
add S5,S7,T3 ; A7 cross product sum
ldd XF4,S12 ; MR * A6R
ldd XF11,S11 ; ML * A5L
add,dc zero,zero,S5 ; A7 cross product sum carry
depd,z T3,31,32,S7 ; A7 cross product sum << 32
ldd XF6,S14 ; ML * A6L
ldd XF13,S13 ; MR * A7R
shrpd S5,T3,32,S5 ; A7 carry | cross product sum >> 32
add S2,S8,S8 ; M * A4 right doubleword
ldd XF15,S15 ; ML * A7L
add,dc S0,S10,S10 ; M * A4 left doubleword
add S3,S9,S9 ; M * A5 right doubleword
add,dc S1,S11,S11 ; M * A5 left doubleword
add S6,S12,S12 ; M * A6 right doubleword
ldd 32(pR),S0 ; Addend word 4
ldd 40(pR),S1 ; Addend word 5
add,dc S4,S14,S14 ; M * A6 left doubleword
add S7,S13,S13 ; M * A7 right doubleword
ldd 48(pR),S2 ; Addend word 6
ldd 56(pR),S3 ; Addend word 7
add,dc S5,S15,S15 ; M * A7 left doubleword
add S8,T2,S8 ; P4 doubleword
ldd 64(pR),S4 ; Addend word 8
ldd SV5,s5 ; restore s5
add,dc S10,S9,S9 ; P5 doubleword
add,dc S11,S12,S12 ; P6 doubleword
ldd SV6,s6 ; restore s6
ldd SV7,s7 ; restore s7
add,dc S14,S13,S13 ; P7 doubleword
add,dc zero,S15,S15 ; P8 doubleword
add S0,S8,S8 ; new R4 doubleword
ldd SV0,s0 ; restore s0
std S8,32(pR) ; save R4
add,dc S1,S9,S9 ; new R5 doubleword
ldd SV1,s1 ; restore s1
std S9,40(pR) ; save R5
add,dc S2,S12,S12 ; new R6 doubleword
ldd SV2,s2 ; restore s2
std S12,48(pR) ; save R6
add,dc S3,S13,S13 ; new R7 doubleword
ldd SV3,s3 ; restore s3
std S13,56(pR) ; save R7
add,dc S4,S15,S15 ; new R8 doubleword
ldd SV4,s4 ; restore s4
std S15,64(pR) ; save result[8]
add,dc zero,zero,v0 ; return carry from R8
CMPIB,*= 0,v0,$L0 ; if no overflow, exit
LDO 8(pR),pR
$FINAL1 ; Final carry propagation
LDD 64(pR),v0
LDO 8(pR),pR
ADDI 1,v0,v0
CMPIB,*= 0,v0,$FINAL1 ; Keep looping if there is a carry.
STD v0,56(pR)
$L0
bv zero(rp) ; -> caller
ldo -ST_SZ(sp),sp ; pop stack
/* ====================================================================== */
/* end of module */
/* ====================================================================== */
.LEAVE
.PROCEND
.SPACE $TEXT$
.SUBSPA $CODE$
.EXPORT multacc512,ENTRY
.end

View File

@@ -1,929 +0,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/
;
; 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 MAXPY multiple-precision integer arithmetic.
;
; The Initial Developer of the Original Code is the Hewlett-Packard Company.
; Portions created by Hewlett-Packard Company are
; Copyright (C) 1997 Hewlett-Packard Company. All Rights Reserved.
;
; Contributor(s):
; coded by: William B. Ackerman
;
; Alternatively, the contents of this file may be used under the
; terms of the GNU General Public License Version 2 or later (the
; "GPL"), in which case the provisions of the GPL are applicable
; instead of those above. If you wish to allow use of your
; version of this file only under the terms of the GPL and not to
; allow others to use your version of this file under the MPL,
; indicate your decision by deleting the provisions above and
; replace them with the notice and other provisions required by
; the GPL. If you do not delete the provisions above, a recipient
; may use your version of this file under either the MPL or the
; GPL.
#ifdef __LP64__
.LEVEL 2.0W
#else
; .LEVEL 1.1
; .ALLOW 2.0N
.LEVEL 2.0N
#endif
.SPACE $TEXT$,SORT=8
.SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
; ***************************************************************
;
; maxpy_[little/big]
;
; ***************************************************************
; There is no default -- you must specify one or the other.
#define LITTLE_WORDIAN 1
#ifdef LITTLE_WORDIAN
#define EIGHT 8
#define SIXTEEN 16
#define THIRTY_TWO 32
#define UN_EIGHT -8
#define UN_SIXTEEN -16
#define UN_TWENTY_FOUR -24
#endif
#ifdef BIG_WORDIAN
#define EIGHT -8
#define SIXTEEN -16
#define THIRTY_TWO -32
#define UN_EIGHT 8
#define UN_SIXTEEN 16
#define UN_TWENTY_FOUR 24
#endif
; This performs a multiple-precision integer version of "daxpy",
; Using the selected addressing direction. "Little-wordian" means that
; the least significant word of a number is stored at the lowest address.
; "Big-wordian" means that the most significant word is at the lowest
; address. Either way, the incoming address of the vector is that
; of the least significant word. That means that, for little-wordian
; addressing, we move the address upward as we propagate carries
; from the least significant word to the most significant. For
; big-wordian we move the address downward.
; We use the following registers:
;
; r2 return PC, of course
; r26 = arg1 = length
; r25 = arg2 = address of scalar
; r24 = arg3 = multiplicand vector
; r23 = arg4 = result vector
;
; fr9 = scalar loaded once only from r25
; The cycle counts shown in the bodies below are simply the result of a
; scheduling by hand. The actual PCX-U hardware does it differently.
; The intention is that the overall speed is the same.
; The pipeline startup and shutdown code is constructed in the usual way,
; by taking the loop bodies and removing unnecessary instructions.
; We have left the comments describing cycle numbers in the code.
; These are intended for reference when comparing with the main loop,
; and have no particular relationship to actual cycle numbers.
#ifdef LITTLE_WORDIAN
maxpy_little
#else
maxpy_big
#endif
.PROC
.CALLINFO FRAME=120,ENTRY_GR=%r4
.ENTER
; Of course, real men don't use the sissy "enter" and "leave" commands.
; They write their own stack manipulation stuff. Unfortunately,
; that doesn't generate complete unwind info, whereas "enter" and
; "leave" (if the documentation is to be believed) do so. Therefore,
; we use the sissy commands. We have verified (by real-man methods)
; that the above command generates what we want:
; STW,MA %r3,128(%sp)
; STW %r4,-124(%sp)
ADDIB,< -1,%r26,$L0 ; If N = 0, exit immediately.
FLDD 0(%r25),%fr9 ; fr9 = scalar
; First startup
FLDD 0(%r24),%fr24 ; Cycle 1
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
CMPIB,> 3,%r26,$N_IS_SMALL ; Pick out cases N = 1, 2, or 3
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
FLDD EIGHT(%r24),%fr28 ; Cycle 8
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
FSTD %fr24,-96(%sp)
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
FSTD %fr25,-80(%sp)
LDO SIXTEEN(%r24),%r24 ; Cycle 12
FSTD %fr31,-64(%sp)
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
FSTD %fr27,-48(%sp)
; Second startup
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
FSTD %fr30,-56(%sp)
FLDD 0(%r24),%fr24
FSTD %fr26,-88(%sp) ; Cycle 2
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
FSTD %fr28,-104(%sp)
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
LDD -96(%sp),%r3
FSTD %fr29,-72(%sp)
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
LDD -64(%sp),%r19
LDD -80(%sp),%r21
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
LDD -56(%sp),%r20
ADD %r21,%r3,%r3
ADD,DC %r20,%r19,%r19 ; Cycle 7
LDD -88(%sp),%r4
SHRPD %r3,%r0,32,%r21
LDD -48(%sp),%r1
FLDD EIGHT(%r24),%fr28 ; Cycle 8
LDD -104(%sp),%r31
ADD,DC %r0,%r0,%r20
SHRPD %r19,%r3,32,%r3
LDD -72(%sp),%r29 ; Cycle 9
SHRPD %r20,%r19,32,%r20
ADD %r21,%r1,%r1
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
ADD,DC %r3,%r4,%r4
FSTD %fr24,-96(%sp)
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
ADD,DC %r0,%r20,%r20
LDD 0(%r23),%r3
FSTD %fr25,-80(%sp)
LDO SIXTEEN(%r24),%r24 ; Cycle 12
FSTD %fr31,-64(%sp)
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
ADD %r0,%r0,%r0 ; clear the carry bit
ADDIB,<= -4,%r26,$ENDLOOP ; actually happens in cycle 12
FSTD %fr27,-48(%sp)
; MFCTL %cr16,%r21 ; for timing
; STD %r21,-112(%sp)
; Here is the loop.
$LOOP XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
ADD,DC %r29,%r4,%r4
FSTD %fr30,-56(%sp)
FLDD 0(%r24),%fr24
LDO SIXTEEN(%r23),%r23 ; Cycle 2
ADD,DC %r0,%r20,%r20
FSTD %fr26,-88(%sp)
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
ADD %r3,%r1,%r1
FSTD %fr28,-104(%sp)
LDD UN_EIGHT(%r23),%r21
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
ADD,DC %r21,%r4,%r28
FSTD %fr29,-72(%sp)
LDD -96(%sp),%r3
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
ADD,DC %r20,%r31,%r22
LDD -64(%sp),%r19
LDD -80(%sp),%r21
XMPYU %fr9L,%fr24R,%fr24 ; Cycle 6
ADD %r21,%r3,%r3
LDD -56(%sp),%r20
STD %r1,UN_SIXTEEN(%r23)
ADD,DC %r20,%r19,%r19 ; Cycle 7
SHRPD %r3,%r0,32,%r21
LDD -88(%sp),%r4
LDD -48(%sp),%r1
ADD,DC %r0,%r0,%r20 ; Cycle 8
SHRPD %r19,%r3,32,%r3
FLDD EIGHT(%r24),%fr28
LDD -104(%sp),%r31
SHRPD %r20,%r19,32,%r20 ; Cycle 9
ADD %r21,%r1,%r1
STD %r28,UN_EIGHT(%r23)
LDD -72(%sp),%r29
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
ADD,DC %r3,%r4,%r4
FSTD %fr24,-96(%sp)
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
ADD,DC %r0,%r20,%r20
FSTD %fr25,-80(%sp)
LDD 0(%r23),%r3
LDO SIXTEEN(%r24),%r24 ; Cycle 12
FSTD %fr31,-64(%sp)
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
ADD %r22,%r1,%r1
ADDIB,> -2,%r26,$LOOP ; actually happens in cycle 12
FSTD %fr27,-48(%sp)
$ENDLOOP
; Shutdown code, first stage.
; MFCTL %cr16,%r21 ; for timing
; STD %r21,UN_SIXTEEN(%r23)
; LDD -112(%sp),%r21
; STD %r21,UN_EIGHT(%r23)
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
ADD,DC %r29,%r4,%r4
CMPIB,= 0,%r26,$ONEMORE
FSTD %fr30,-56(%sp)
LDO SIXTEEN(%r23),%r23 ; Cycle 2
ADD,DC %r0,%r20,%r20
FSTD %fr26,-88(%sp)
ADD %r3,%r1,%r1 ; Cycle 3
FSTD %fr28,-104(%sp)
LDD UN_EIGHT(%r23),%r21
ADD,DC %r21,%r4,%r28 ; Cycle 4
FSTD %fr29,-72(%sp)
STD %r28,UN_EIGHT(%r23) ; moved up from cycle 9
LDD -96(%sp),%r3
ADD,DC %r20,%r31,%r22 ; Cycle 5
STD %r1,UN_SIXTEEN(%r23)
$JOIN4
LDD -64(%sp),%r19
LDD -80(%sp),%r21
ADD %r21,%r3,%r3 ; Cycle 6
LDD -56(%sp),%r20
ADD,DC %r20,%r19,%r19 ; Cycle 7
SHRPD %r3,%r0,32,%r21
LDD -88(%sp),%r4
LDD -48(%sp),%r1
ADD,DC %r0,%r0,%r20 ; Cycle 8
SHRPD %r19,%r3,32,%r3
LDD -104(%sp),%r31
SHRPD %r20,%r19,32,%r20 ; Cycle 9
ADD %r21,%r1,%r1
LDD -72(%sp),%r29
ADD,DC %r3,%r4,%r4 ; Cycle 10
ADD,DC %r0,%r20,%r20 ; Cycle 11
LDD 0(%r23),%r3
ADD %r22,%r1,%r1 ; Cycle 13
; Shutdown code, second stage.
ADD,DC %r29,%r4,%r4 ; Cycle 1
LDO SIXTEEN(%r23),%r23 ; Cycle 2
ADD,DC %r0,%r20,%r20
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
ADD %r3,%r1,%r1
ADD,DC %r21,%r4,%r28 ; Cycle 4
ADD,DC %r20,%r31,%r22 ; Cycle 5
STD %r1,UN_SIXTEEN(%r23); Cycle 6
STD %r28,UN_EIGHT(%r23) ; Cycle 9
LDD 0(%r23),%r3 ; Cycle 11
; Shutdown code, third stage.
LDO SIXTEEN(%r23),%r23
ADD %r3,%r22,%r1
$JOIN1 ADD,DC %r0,%r0,%r21
CMPIB,*= 0,%r21,$L0 ; if no overflow, exit
STD %r1,UN_SIXTEEN(%r23)
; Final carry propagation
$FINAL1 LDO EIGHT(%r23),%r23
LDD UN_SIXTEEN(%r23),%r21
ADDI 1,%r21,%r21
CMPIB,*= 0,%r21,$FINAL1 ; Keep looping if there is a carry.
STD %r21,UN_SIXTEEN(%r23)
B $L0
NOP
; Here is the code that handles the difficult cases N=1, N=2, and N=3.
; We do the usual trick -- branch out of the startup code at appropriate
; points, and branch into the shutdown code.
$N_IS_SMALL
CMPIB,= 0,%r26,$N_IS_ONE
FSTD %fr24,-96(%sp) ; Cycle 10
FLDD EIGHT(%r24),%fr28 ; Cycle 8
XMPYU %fr9L,%fr28R,%fr31 ; Cycle 10
XMPYU %fr9R,%fr28L,%fr30 ; Cycle 11
FSTD %fr25,-80(%sp)
FSTD %fr31,-64(%sp) ; Cycle 12
XMPYU %fr9R,%fr28R,%fr29 ; Cycle 13
FSTD %fr27,-48(%sp)
XMPYU %fr9L,%fr28L,%fr28 ; Cycle 1
CMPIB,= 2,%r26,$N_IS_THREE
FSTD %fr30,-56(%sp)
; N = 2
FSTD %fr26,-88(%sp) ; Cycle 2
FSTD %fr28,-104(%sp) ; Cycle 3
LDD -96(%sp),%r3 ; Cycle 4
FSTD %fr29,-72(%sp)
B $JOIN4
ADD %r0,%r0,%r22
$N_IS_THREE
FLDD SIXTEEN(%r24),%fr24
FSTD %fr26,-88(%sp) ; Cycle 2
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
FSTD %fr28,-104(%sp)
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
LDD -96(%sp),%r3
FSTD %fr29,-72(%sp)
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
LDD -64(%sp),%r19
LDD -80(%sp),%r21
B $JOIN3
ADD %r0,%r0,%r22
$N_IS_ONE
FSTD %fr25,-80(%sp)
FSTD %fr27,-48(%sp)
FSTD %fr26,-88(%sp) ; Cycle 2
B $JOIN5
ADD %r0,%r0,%r22
; We came out of the unrolled loop with wrong parity. Do one more
; single cycle. This is quite tricky, because of the way the
; carry chains and SHRPD chains have been chopped up.
$ONEMORE
FLDD 0(%r24),%fr24
LDO SIXTEEN(%r23),%r23 ; Cycle 2
ADD,DC %r0,%r20,%r20
FSTD %fr26,-88(%sp)
XMPYU %fr9R,%fr24R,%fr27 ; Cycle 3
FSTD %fr28,-104(%sp)
LDD UN_EIGHT(%r23),%r21
ADD %r3,%r1,%r1
XMPYU %fr9R,%fr24L,%fr25 ; Cycle 4
ADD,DC %r21,%r4,%r28
STD %r28,UN_EIGHT(%r23) ; moved from cycle 9
LDD -96(%sp),%r3
FSTD %fr29,-72(%sp)
XMPYU %fr9L,%fr24L,%fr26 ; Cycle 5
ADD,DC %r20,%r31,%r22
LDD -64(%sp),%r19
LDD -80(%sp),%r21
STD %r1,UN_SIXTEEN(%r23); Cycle 6
$JOIN3
XMPYU %fr9L,%fr24R,%fr24
LDD -56(%sp),%r20
ADD %r21,%r3,%r3
ADD,DC %r20,%r19,%r19 ; Cycle 7
LDD -88(%sp),%r4
SHRPD %r3,%r0,32,%r21
LDD -48(%sp),%r1
LDD -104(%sp),%r31 ; Cycle 8
ADD,DC %r0,%r0,%r20
SHRPD %r19,%r3,32,%r3
LDD -72(%sp),%r29 ; Cycle 9
SHRPD %r20,%r19,32,%r20
ADD %r21,%r1,%r1
ADD,DC %r3,%r4,%r4 ; Cycle 10
FSTD %fr24,-96(%sp)
ADD,DC %r0,%r20,%r20 ; Cycle 11
LDD 0(%r23),%r3
FSTD %fr25,-80(%sp)
ADD %r22,%r1,%r1 ; Cycle 13
FSTD %fr27,-48(%sp)
; Shutdown code, stage 1-1/2.
ADD,DC %r29,%r4,%r4 ; Cycle 1
LDO SIXTEEN(%r23),%r23 ; Cycle 2
ADD,DC %r0,%r20,%r20
FSTD %fr26,-88(%sp)
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
ADD %r3,%r1,%r1
ADD,DC %r21,%r4,%r28 ; Cycle 4
STD %r28,UN_EIGHT(%r23) ; moved from cycle 9
ADD,DC %r20,%r31,%r22 ; Cycle 5
STD %r1,UN_SIXTEEN(%r23)
$JOIN5
LDD -96(%sp),%r3 ; moved from cycle 4
LDD -80(%sp),%r21
ADD %r21,%r3,%r3 ; Cycle 6
ADD,DC %r0,%r0,%r19 ; Cycle 7
LDD -88(%sp),%r4
SHRPD %r3,%r0,32,%r21
LDD -48(%sp),%r1
SHRPD %r19,%r3,32,%r3 ; Cycle 8
ADD %r21,%r1,%r1 ; Cycle 9
ADD,DC %r3,%r4,%r4 ; Cycle 10
LDD 0(%r23),%r3 ; Cycle 11
ADD %r22,%r1,%r1 ; Cycle 13
; Shutdown code, stage 2-1/2.
ADD,DC %r0,%r4,%r4 ; Cycle 1
LDO SIXTEEN(%r23),%r23 ; Cycle 2
LDD UN_EIGHT(%r23),%r21 ; Cycle 3
ADD %r3,%r1,%r1
STD %r1,UN_SIXTEEN(%r23)
ADD,DC %r21,%r4,%r1
B $JOIN1
LDO EIGHT(%r23),%r23
; exit
$L0
.LEAVE
; We have verified that the above command generates what we want:
; LDW -124(%sp),%r4
; BVE (%r2)
; LDW,MB -128(%sp),%r3
.PROCEND
; ***************************************************************
;
; add_diag_[little/big]
;
; ***************************************************************
; The arguments are as follows:
; r2 return PC, of course
; r26 = arg1 = length
; r25 = arg2 = vector to square
; r24 = arg3 = result vector
#ifdef LITTLE_WORDIAN
add_diag_little
#else
add_diag_big
#endif
.PROC
.CALLINFO FRAME=120,ENTRY_GR=%r4
.ENTER
ADDIB,< -1,%r26,$Z0 ; If N=0, exit immediately.
NOP
; Startup code
FLDD 0(%r25),%fr7 ; Cycle 2 (alternate body)
XMPYU %fr7R,%fr7R,%fr29 ; Cycle 4
XMPYU %fr7L,%fr7R,%fr27 ; Cycle 5
XMPYU %fr7L,%fr7L,%fr30
LDO SIXTEEN(%r25),%r25 ; Cycle 6
FSTD %fr29,-88(%sp)
FSTD %fr27,-72(%sp) ; Cycle 7
CMPIB,= 0,%r26,$DIAG_N_IS_ONE ; Cycle 1 (main body)
FSTD %fr30,-96(%sp)
FLDD UN_EIGHT(%r25),%fr7 ; Cycle 2
LDD -88(%sp),%r22 ; Cycle 3
LDD -72(%sp),%r31 ; Cycle 4
XMPYU %fr7R,%fr7R,%fr28
XMPYU %fr7L,%fr7R,%fr24 ; Cycle 5
XMPYU %fr7L,%fr7L,%fr31
LDD -96(%sp),%r20 ; Cycle 6
FSTD %fr28,-80(%sp)
ADD %r0,%r0,%r0 ; clear the carry bit
ADDIB,<= -2,%r26,$ENDDIAGLOOP ; Cycle 7
FSTD %fr24,-64(%sp)
; Here is the loop. It is unrolled twice, modelled after the "alternate body" and then the "main body".
$DIAGLOOP
SHRPD %r31,%r0,31,%r3 ; Cycle 1 (alternate body)
LDO SIXTEEN(%r25),%r25
LDD 0(%r24),%r1
FSTD %fr31,-104(%sp)
SHRPD %r0,%r31,31,%r4 ; Cycle 2
ADD,DC %r22,%r3,%r3
FLDD UN_SIXTEEN(%r25),%fr7
ADD,DC %r0,%r20,%r20 ; Cycle 3
ADD %r1,%r3,%r3
XMPYU %fr7R,%fr7R,%fr29 ; Cycle 4
LDD -80(%sp),%r21
STD %r3,0(%r24)
XMPYU %fr7L,%fr7R,%fr27 ; Cycle 5
XMPYU %fr7L,%fr7L,%fr30
LDD -64(%sp),%r29
LDD EIGHT(%r24),%r1
ADD,DC %r4,%r20,%r20 ; Cycle 6
LDD -104(%sp),%r19
FSTD %fr29,-88(%sp)
ADD %r20,%r1,%r1 ; Cycle 7
FSTD %fr27,-72(%sp)
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
LDO THIRTY_TWO(%r24),%r24
LDD UN_SIXTEEN(%r24),%r28
FSTD %fr30,-96(%sp)
SHRPD %r0,%r29,31,%r3 ; Cycle 2
ADD,DC %r21,%r4,%r4
FLDD UN_EIGHT(%r25),%fr7
STD %r1,UN_TWENTY_FOUR(%r24)
ADD,DC %r0,%r19,%r19 ; Cycle 3
ADD %r28,%r4,%r4
XMPYU %fr7R,%fr7R,%fr28 ; Cycle 4
LDD -88(%sp),%r22
STD %r4,UN_SIXTEEN(%r24)
XMPYU %fr7L,%fr7R,%fr24 ; Cycle 5
XMPYU %fr7L,%fr7L,%fr31
LDD -72(%sp),%r31
LDD UN_EIGHT(%r24),%r28
ADD,DC %r3,%r19,%r19 ; Cycle 6
LDD -96(%sp),%r20
FSTD %fr28,-80(%sp)
ADD %r19,%r28,%r28 ; Cycle 7
FSTD %fr24,-64(%sp)
ADDIB,> -2,%r26,$DIAGLOOP ; Cycle 8
STD %r28,UN_EIGHT(%r24)
$ENDDIAGLOOP
ADD,DC %r0,%r22,%r22
CMPIB,= 0,%r26,$ONEMOREDIAG
SHRPD %r31,%r0,31,%r3
; Shutdown code, first stage.
FSTD %fr31,-104(%sp) ; Cycle 1 (alternate body)
LDD 0(%r24),%r28
SHRPD %r0,%r31,31,%r4 ; Cycle 2
ADD %r3,%r22,%r3
ADD,DC %r0,%r20,%r20 ; Cycle 3
LDD -80(%sp),%r21
ADD %r3,%r28,%r3
LDD -64(%sp),%r29 ; Cycle 4
STD %r3,0(%r24)
LDD EIGHT(%r24),%r1 ; Cycle 5
LDO SIXTEEN(%r25),%r25 ; Cycle 6
LDD -104(%sp),%r19
ADD,DC %r4,%r20,%r20
ADD %r20,%r1,%r1 ; Cycle 7
ADD,DC %r0,%r21,%r21 ; Cycle 8
STD %r1,EIGHT(%r24)
; Shutdown code, second stage.
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
LDO THIRTY_TWO(%r24),%r24
LDD UN_SIXTEEN(%r24),%r1
SHRPD %r0,%r29,31,%r3 ; Cycle 2
ADD %r4,%r21,%r4
ADD,DC %r0,%r19,%r19 ; Cycle 3
ADD %r4,%r1,%r4
STD %r4,UN_SIXTEEN(%r24); Cycle 4
LDD UN_EIGHT(%r24),%r28 ; Cycle 5
ADD,DC %r3,%r19,%r19 ; Cycle 6
ADD %r19,%r28,%r28 ; Cycle 7
ADD,DC %r0,%r0,%r22 ; Cycle 8
CMPIB,*= 0,%r22,$Z0 ; if no overflow, exit
STD %r28,UN_EIGHT(%r24)
; Final carry propagation
$FDIAG2
LDO EIGHT(%r24),%r24
LDD UN_EIGHT(%r24),%r26
ADDI 1,%r26,%r26
CMPIB,*= 0,%r26,$FDIAG2 ; Keep looping if there is a carry.
STD %r26,UN_EIGHT(%r24)
B $Z0
NOP
; Here is the code that handles the difficult case N=1.
; We do the usual trick -- branch out of the startup code at appropriate
; points, and branch into the shutdown code.
$DIAG_N_IS_ONE
LDD -88(%sp),%r22
LDD -72(%sp),%r31
B $JOINDIAG
LDD -96(%sp),%r20
; We came out of the unrolled loop with wrong parity. Do one more
; single cycle. This is the "alternate body". It will, of course,
; give us opposite registers from the other case, so we need
; completely different shutdown code.
$ONEMOREDIAG
FSTD %fr31,-104(%sp) ; Cycle 1 (alternate body)
LDD 0(%r24),%r28
FLDD 0(%r25),%fr7 ; Cycle 2
SHRPD %r0,%r31,31,%r4
ADD %r3,%r22,%r3
ADD,DC %r0,%r20,%r20 ; Cycle 3
LDD -80(%sp),%r21
ADD %r3,%r28,%r3
LDD -64(%sp),%r29 ; Cycle 4
STD %r3,0(%r24)
XMPYU %fr7R,%fr7R,%fr29
LDD EIGHT(%r24),%r1 ; Cycle 5
XMPYU %fr7L,%fr7R,%fr27
XMPYU %fr7L,%fr7L,%fr30
LDD -104(%sp),%r19 ; Cycle 6
FSTD %fr29,-88(%sp)
ADD,DC %r4,%r20,%r20
FSTD %fr27,-72(%sp) ; Cycle 7
ADD %r20,%r1,%r1
ADD,DC %r0,%r21,%r21 ; Cycle 8
STD %r1,EIGHT(%r24)
; Shutdown code, first stage.
SHRPD %r29,%r0,31,%r4 ; Cycle 1 (main body)
LDO THIRTY_TWO(%r24),%r24
FSTD %fr30,-96(%sp)
LDD UN_SIXTEEN(%r24),%r1
SHRPD %r0,%r29,31,%r3 ; Cycle 2
ADD %r4,%r21,%r4
ADD,DC %r0,%r19,%r19 ; Cycle 3
LDD -88(%sp),%r22
ADD %r4,%r1,%r4
LDD -72(%sp),%r31 ; Cycle 4
STD %r4,UN_SIXTEEN(%r24)
LDD UN_EIGHT(%r24),%r28 ; Cycle 5
LDD -96(%sp),%r20 ; Cycle 6
ADD,DC %r3,%r19,%r19
ADD %r19,%r28,%r28 ; Cycle 7
ADD,DC %r0,%r22,%r22 ; Cycle 8
STD %r28,UN_EIGHT(%r24)
; Shutdown code, second stage.
$JOINDIAG
SHRPD %r31,%r0,31,%r3 ; Cycle 1 (alternate body)
LDD 0(%r24),%r28
SHRPD %r0,%r31,31,%r4 ; Cycle 2
ADD %r3,%r22,%r3
ADD,DC %r0,%r20,%r20 ; Cycle 3
ADD %r3,%r28,%r3
STD %r3,0(%r24) ; Cycle 4
LDD EIGHT(%r24),%r1 ; Cycle 5
ADD,DC %r4,%r20,%r20
ADD %r20,%r1,%r1 ; Cycle 7
ADD,DC %r0,%r0,%r21 ; Cycle 8
CMPIB,*= 0,%r21,$Z0 ; if no overflow, exit
STD %r1,EIGHT(%r24)
; Final carry propagation
$FDIAG1
LDO EIGHT(%r24),%r24
LDD EIGHT(%r24),%r26
ADDI 1,%r26,%r26
CMPIB,*= 0,%r26,$FDIAG1 ; Keep looping if there is a carry.
STD %r26,EIGHT(%r24)
$Z0
.LEAVE
.PROCEND
; .ALLOW
.SPACE $TEXT$
.SUBSPA $CODE$
#ifdef LITTLE_WORDIAN
.EXPORT maxpy_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
.EXPORT add_diag_little,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
#else
.EXPORT maxpy_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,LONG_RETURN
.EXPORT add_diag_big,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,LONG_RETURN
#endif
.END
; How to use "maxpy_PA20_little" and "maxpy_PA20_big"
;
; The routine "maxpy_PA20_little" or "maxpy_PA20_big"
; performs a 64-bit x any-size multiply, and adds the
; result to an area of memory. That is, it performs
; something like
;
; A B C D
; * Z
; __________
; P Q R S T
;
; and then adds the "PQRST" vector into an area of memory,
; handling all carries.
;
; Digression on nomenclature and endian-ness:
;
; Each of the capital letters in the above represents a 64-bit
; quantity. That is, you could think of the discussion as
; being in terms of radix-16-quintillion arithmetic. The data
; type being manipulated is "unsigned long long int". This
; requires the 64-bit extension of the HP-UX C compiler,
; available at release 10. You need these compiler flags to
; enable these extensions:
;
; -Aa +e +DA2.0 +DS2.0
;
; (The first specifies ANSI C, the second enables the
; extensions, which are beyond ANSI C, and the third and
; fourth tell the compiler to use whatever features of the
; PA2.0 architecture it wishes, in order to made the code more
; efficient. Since the presence of the assembly code will
; make the program unable to run on anything less than PA2.0,
; you might as well gain the performance enhancements in the C
; code as well.)
;
; Questions of "endian-ness" often come up, usually in the
; context of byte ordering in a word. These routines have a
; similar issue, that could be called "wordian-ness".
; Independent of byte ordering (PA is always big-endian), one
; can make two choices when representing extremely large
; numbers as arrays of 64-bit doublewords in memory.
;
; "Little-wordian" layout means that the least significant
; word of a number is stored at the lowest address.
;
; MSW LSW
; | |
; V V
;
; A B C D E
;
; ^ ^ ^
; | | |____ address 0
; | |
; | |_______address 8
; |
; address 32
;
; "Big-wordian" means that the most significant word is at the
; lowest address.
;
; MSW LSW
; | |
; V V
;
; A B C D E
;
; ^ ^ ^
; | | |____ address 32
; | |
; | |_______address 24
; |
; address 0
;
; When you compile the file, you must specify one or the other, with
; a switch "-DLITTLE_WORDIAN" or "-DBIG_WORDIAN".
;
; Incidentally, you assemble this file as part of your
; project with the same C compiler as the rest of the program.
; My "makefile" for a superprecision arithmetic package has
; the following stuff:
;
; # definitions:
; CC = cc -Aa +e -z +DA2.0 +DS2.0 +w1
; CFLAGS = +O3
; LDFLAGS = -L /usr/lib -Wl,-aarchive
;
; # general build rule for ".s" files:
; .s.o:
; $(CC) $(CFLAGS) -c $< -DBIG_WORDIAN
;
; # Now any bind step that calls for pa20.o will assemble pa20.s
;
; End of digression, back to arithmetic:
;
; The way we multiply two huge numbers is, of course, to multiply
; the "ABCD" vector by each of the "WXYZ" doublewords, adding
; the result vectors with increasing offsets, the way we learned
; in school, back before we all used calculators:
;
; A B C D
; * W X Y Z
; __________
; P Q R S T
; E F G H I
; M N O P Q
; + R S T U V
; _______________
; F I N A L S U M
;
; So we call maxpy_PA20_big (in my case; my package is
; big-wordian) repeatedly, giving the W, X, Y, and Z arguments
; in turn as the "scalar", and giving the "ABCD" vector each
; time. We direct it to add its result into an area of memory
; that we have cleared at the start. We skew the exact
; location into that area with each call.
;
; The prototype for the function is
;
; extern void maxpy_PA20_big(
; int length, /* Number of doublewords in the multiplicand vector. */
; const long long int *scalaraddr, /* Address to fetch the scalar. */
; const long long int *multiplicand, /* The multiplicand vector. */
; long long int *result); /* Where to accumulate the result. */
;
; (You should place a copy of this prototype in an include file
; or in your C file.)
;
; Now, IN ALL CASES, the given address for the multiplicand or
; the result is that of the LEAST SIGNIFICANT DOUBLEWORD.
; That word is, of course, the word at which the routine
; starts processing. "maxpy_PA20_little" then increases the
; addresses as it computes. "maxpy_PA20_big" decreases them.
;
; In our example above, "length" would be 4 in each case.
; "multiplicand" would be the "ABCD" vector. Specifically,
; the address of the element "D". "scalaraddr" would be the
; address of "W", "X", "Y", or "Z" on the four calls that we
; would make. (The order doesn't matter, of course.)
; "result" would be the appropriate address in the result
; area. When multiplying by "Z", that would be the least
; significant word. When multiplying by "Y", it would be the
; next higher word (8 bytes higher if little-wordian; 8 bytes
; lower if big-wordian), and so on. The size of the result
; area must be the the sum of the sizes of the multiplicand
; and multiplier vectors, and must be initialized to zero
; before we start.
;
; Whenever the routine adds its partial product into the result
; vector, it follows carry chains as far as they need to go.
;
; Here is the super-precision multiply routine that I use for
; my package. The package is big-wordian. I have taken out
; handling of exponents (it's a floating point package):
;
; static void mul_PA20(
; int size,
; const long long int *arg1,
; const long long int *arg2,
; long long int *result)
; {
; int i;
;
; for (i=0 ; i<2*size ; i++) result[i] = 0ULL;
;
; for (i=0 ; i<size ; i++) {
; maxpy_PA20_big(size, &arg2[i], &arg1[size-1], &result[size+i]);
; }
; }

View File

@@ -1,54 +0,0 @@
#/bin/sh
#
# ***** 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 script to change the system id in an object file from PA-RISC 2.0 to 1.1.
#
# The Initial Developer of the Original Code is
# Hewlett-Packard Company.
# Portions created by the Initial Developer are Copyright (C) 1999
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# wrapped by Dennis Handly on Tue Mar 23 15:23:43 1999
#
# 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 *****
# script to change the system id in an object file from PA-RISC 2.0 to 1.1
adb -w $1 << EOF
?m 0 -1 0
0x0?X
0x0?W (@0x0&~0x40000)|(~@0x0&0x40000)
0?"change checksum"
0x7c?X
0x7c?W (@0x7c&~0x40000)|(~@0x7c&0x40000)
$q
EOF
exit 0

View File

@@ -1,62 +0,0 @@
/*
* logtab.h
*
* Arbitrary precision integer arithmetic 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 MPI Arbitrary Precision Integer Arithmetic library.
*
* The Initial Developer of the Original Code is
* Michael J. Fromberger.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: logtab.h,v 1.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
const float s_logv_2[] = {
0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */
0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */
0.333333333f, 0.315464877f, 0.301029996f, 0.289064826f, /* 8 9 10 11 */
0.278942946f, 0.270238154f, 0.262649535f, 0.255958025f, /* 12 13 14 15 */
0.250000000f, 0.244650542f, 0.239812467f, 0.235408913f, /* 16 17 18 19 */
0.231378213f, 0.227670249f, 0.224243824f, 0.221064729f, /* 20 21 22 23 */
0.218104292f, 0.215338279f, 0.212746054f, 0.210309918f, /* 24 25 26 27 */
0.208014598f, 0.205846832f, 0.203795047f, 0.201849087f, /* 28 29 30 31 */
0.200000000f, 0.198239863f, 0.196561632f, 0.194959022f, /* 32 33 34 35 */
0.193426404f, 0.191958720f, 0.190551412f, 0.189200360f, /* 36 37 38 39 */
0.187901825f, 0.186652411f, 0.185449023f, 0.184288833f, /* 40 41 42 43 */
0.183169251f, 0.182087900f, 0.181042597f, 0.180031327f, /* 44 45 46 47 */
0.179052232f, 0.178103594f, 0.177183820f, 0.176291434f, /* 48 49 50 51 */
0.175425064f, 0.174583430f, 0.173765343f, 0.172969690f, /* 52 53 54 55 */
0.172195434f, 0.171441601f, 0.170707280f, 0.169991616f, /* 56 57 58 59 */
0.169293808f, 0.168613099f, 0.167948779f, 0.167300179f, /* 60 61 62 63 */
0.166666667f
};

View File

@@ -1,64 +0,0 @@
#!/usr/linguist/bin/perl
#
# make-logtab
#
# Generate a table of logarithms of 2 in various bases, for use in
# estimating the output sizes of various bases.
# ***** 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 MPI Arbitrary Precision Integer Arithmetic
# library.
#
# 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, 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: make-logtab,v 1.4 2005-02-02 22:28:22 gerv%gerv.net Exp $
$ARRAYNAME = $ENV{'ARRAYNAME'} || "s_logv_2";
$ARRAYTYPE = $ENV{'ARRAYTYPE'} || "float";
printf("const %s %s[] = {\n %0.9ff, %0.9ff, ",
$ARRAYTYPE, $ARRAYNAME, 0, 0);
$brk = 2;
for($ix = 2; $ix < 64; $ix++) {
printf("%0.9ff, ", (log(2)/log($ix)));
$brk = ($brk + 1) & 3;
if(!$brk) {
printf(" /* %2d %2d %2d %2d */\n ",
$ix - 3, $ix - 2, $ix - 1, $ix);
}
}
printf("%0.9ff\n};\n\n", (log(2)/log($ix)));
exit 0;

View File

@@ -1,133 +0,0 @@
#!/usr/linguist/bin/perl
#
# make-test-arrays
#
# Given a test-arrays file, which specifies the test suite names, the
# names of the functions which perform those test suites, and
# descriptive comments, this script generates C structures for the
# mpi-test program. The input consists of lines of the form:
#
# suite-name:function-name:comment
#
# The output is written to the standard output. Blank lines are
# ignored, and comments beginning with '#' are stripped.
# ***** 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 MPI Arbitrary Precision Integer Arithmetic library.
#
# 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
# 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: make-test-arrays,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
#
# Read parameters from the environment, if available
$NAMEVAR = $ENV{'NAMEVAR'} || "g_names";
$COUNTVAR = $ENV{'COUNTVAR'} || "g_count";
$FUNCVAR = $ENV{'FUNCVAR'} || "g_tests";
$DESCVAR = $ENV{'DESCVAR'} || "g_descs";
$FUNCLEN = 13;
$NAMELEN = 18;
$DESCLEN = 45;
#------------------------------------------------------------------------
# Suck in input from the files on the command line, or standard input
while(<>) {
chomp;
s/\#.*$//;
next if /^\s*$/;
($suite, $func, $desc) = split(/:/, $_);
$tmp = { "suite" => $suite,
"func" => $func,
"desc" => $desc };
push(@item, $tmp);
}
$count = scalar(@item);
$last = pop(@item);
#------------------------------------------------------------------------
# Output the table of names
print "/* Table mapping test suite names to index numbers */\n";
printf("const int %s = %d;\n", $COUNTVAR, $count);
printf("const char *%s[] = {\n", $NAMEVAR);
foreach $elt (@item) {
printf(" \"%s\",%s/* %s%s */\n", $elt->{"suite"},
" " x ($NAMELEN - length($elt->{"suite"})),
$elt->{"desc"},
" " x ($DESCLEN - length($elt->{"desc"})));
}
printf(" \"%s\" %s/* %s%s */\n", $last->{"suite"},
" " x ($NAMELEN - length($last->{"suite"})),
$last->{"desc"},
" " x ($DESCLEN - length($last->{"desc"})));
print "};\n\n";
#------------------------------------------------------------------------
# Output the driver function prototypes
print "/* Test function prototypes */\n";
foreach $elt (@item, $last) {
printf("int %s(void);\n", $elt->{"func"});
}
print "\n";
#------------------------------------------------------------------------
# Output the table of functions
print "/* Table mapping index numbers to functions */\n";
printf("int (*%s[])(void) = {\n ", $FUNCVAR);
$brk = 0;
foreach $elt (@item) {
print($elt->{"func"}, ", ",
" " x ($FUNCLEN - length($elt->{"func"})));
$brk = ($brk + 1) & 3;
print "\n " unless($brk);
}
print $last->{"func"}, "\n};\n\n";
#------------------------------------------------------------------------
# Output the table of descriptions
print "/* Table mapping index numbers to descriptions */\n";
printf("const char *%s[] = {\n", $DESCVAR);
foreach $elt (@item) {
printf(" \"%s\",\n", $elt->{"desc"});
}
printf(" \"%s\"\n};\n\n", $last->{"desc"});
exit 0;

View File

@@ -1,342 +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) 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#include "mpi.h"
#include "mpi-priv.h"
/* #define OLD_WAY 1 */
/* This key is the 1024-bit test key used for speed testing of RSA private
** key ops.
*/
#define CONST const
static CONST unsigned char default_n[128] = {
0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1,
0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39,
0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae,
0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8,
0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62,
0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8,
0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b,
0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17
};
static CONST unsigned char default_d[128] = {
0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80,
0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e,
0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94,
0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d,
0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0,
0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20,
0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee,
0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01
};
#define DEFAULT_ITERS 50
typedef clock_t timetype;
#define gettime(x) *(x) = clock()
#define subtime(a, b) a -= b
#define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC))
#define sec(x) (x / CLOCKS_PER_SEC)
struct TimingContextStr {
timetype start;
timetype end;
timetype interval;
int minutes;
int seconds;
int millisecs;
};
typedef struct TimingContextStr TimingContext;
TimingContext *CreateTimingContext(void)
{
return (TimingContext *)malloc(sizeof(TimingContext));
}
void DestroyTimingContext(TimingContext *ctx)
{
free(ctx);
}
void TimingBegin(TimingContext *ctx)
{
gettime(&ctx->start);
}
static void timingUpdate(TimingContext *ctx)
{
ctx->millisecs = msec(ctx->interval) % 1000;
ctx->seconds = sec(ctx->interval);
ctx->minutes = ctx->seconds / 60;
ctx->seconds %= 60;
}
void TimingEnd(TimingContext *ctx)
{
gettime(&ctx->end);
ctx->interval = ctx->end;
subtime(ctx->interval, ctx->start);
timingUpdate(ctx);
}
char *TimingGenerateString(TimingContext *ctx)
{
static char sBuf[4096];
sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes,
ctx->seconds, ctx->millisecs);
return sBuf;
}
static void
dumpBytes( unsigned char * b, int l)
{
int i;
if (l <= 0)
return;
for (i = 0; i < l; ++i) {
if (i % 16 == 0)
printf("\t");
printf(" %02x", b[i]);
if (i % 16 == 15)
printf("\n");
}
if ((i % 16) != 0)
printf("\n");
printf("\n");
}
static mp_err
testNewFuncs(const unsigned char * modulusBytes, int modulus_len)
{
mp_err mperr = MP_OKAY;
mp_int modulus;
unsigned char buf[512];
mperr = mp_init(&modulus);
mperr = mp_read_unsigned_octets(&modulus, modulusBytes, modulus_len );
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len);
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+1);
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+4);
mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len);
mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1);
mp_clear(&modulus);
return mperr;
}
int
testModExp( const unsigned char * modulusBytes,
const unsigned int expo,
const unsigned char * input,
unsigned char * output,
int modulus_len)
{
mp_err mperr = MP_OKAY;
mp_int modulus;
mp_int base;
mp_int exponent;
mp_int result;
mperr = mp_init(&modulus);
mperr += mp_init(&base);
mperr += mp_init(&exponent);
mperr += mp_init(&result);
/* we initialize all mp_ints unconditionally, even if some fail.
** This guarantees that the DIGITS pointer is valid (even if null).
** So, mp_clear will do the right thing below.
*/
if (mperr == MP_OKAY) {
mperr = mp_read_unsigned_octets(&modulus,
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
mp_set(&exponent, expo);
if (mperr == MP_OKAY) {
#if OLD_WAY
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
#else
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
#endif
if (mperr == MP_OKAY) {
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
}
}
}
mp_clear(&base);
mp_clear(&result);
mp_clear(&modulus);
mp_clear(&exponent);
return (int)mperr;
}
int
doModExp( const unsigned char * modulusBytes,
const unsigned char * exponentBytes,
const unsigned char * input,
unsigned char * output,
int modulus_len)
{
mp_err mperr = MP_OKAY;
mp_int modulus;
mp_int base;
mp_int exponent;
mp_int result;
mperr = mp_init(&modulus);
mperr += mp_init(&base);
mperr += mp_init(&exponent);
mperr += mp_init(&result);
/* we initialize all mp_ints unconditionally, even if some fail.
** This guarantees that the DIGITS pointer is valid (even if null).
** So, mp_clear will do the right thing below.
*/
if (mperr == MP_OKAY) {
mperr = mp_read_unsigned_octets(&modulus,
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len );
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
if (mperr == MP_OKAY) {
#if OLD_WAY
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
#else
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
#endif
if (mperr == MP_OKAY) {
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
}
}
}
mp_clear(&base);
mp_clear(&result);
mp_clear(&modulus);
mp_clear(&exponent);
return (int)mperr;
}
int
main(int argc, char **argv)
{
TimingContext * timeCtx;
char * progName;
long iters = DEFAULT_ITERS;
unsigned int modulus_len;
int i;
int rv;
unsigned char buf [1024];
unsigned char buf2[1024];
progName = strrchr(argv[0], '/');
if (!progName)
progName = strrchr(argv[0], '\\');
progName = progName ? progName+1 : argv[0];
if (argc >= 2) {
iters = atol(argv[1]);
}
if (argc >= 3) {
modulus_len = atol(argv[2]);
} else
modulus_len = sizeof default_n;
/* no library init function !? */
memset(buf, 0x41, sizeof buf);
if (iters < 2) {
testNewFuncs( default_n, modulus_len);
testNewFuncs( default_n+1, modulus_len - 1);
testNewFuncs( default_n+2, modulus_len - 2);
testNewFuncs( default_n+3, modulus_len - 3);
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
rv = testModExp(default_n, 0, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
rv = testModExp(default_n, 1, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
rv = testModExp(default_n, 2, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
rv = testModExp(default_n, 3, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
}
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
if (rv != 0) {
fprintf(stderr, "Error in modexp operation:\n");
exit(1);
}
dumpBytes((unsigned char *)buf2, modulus_len);
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
timeCtx = CreateTimingContext();
TimingBegin(timeCtx);
i = iters;
while (i--) {
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
if (rv != 0) {
fprintf(stderr, "Error in modexp operation\n");
exit(1);
}
}
TimingEnd(timeCtx);
printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx));
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
return 0;
}

View File

@@ -1,329 +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 SPARC optimized Montgomery multiply functions.
*
* The Initial Developer of the Original Code is
* Sun Microsystems Inc.
* Portions created by the Initial Developer are Copyright (C) 1999-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Netscape Communications Corporation
*
* 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: montmulf.c,v 1.7 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
#ifdef SOLARIS
#define RF_INLINE_MACROS 1
#endif
static const double TwoTo16=65536.0;
static const double TwoToMinus16=1.0/65536.0;
static const double Zero=0.0;
static const double TwoTo32=65536.0*65536.0;
static const double TwoToMinus32=1.0/(65536.0*65536.0);
#ifdef RF_INLINE_MACROS
double upper32(double);
double lower32(double, double);
double mod(double, double, double);
void i16_to_d16_and_d32x4(const double * /*1/(2^16)*/,
const double * /* 2^16*/,
const double * /* 0 */,
double * /*result16*/,
double * /* result32 */,
float * /*source - should be unsigned int*
converted to float* */);
#else
#ifdef MP_USE_FLOOR
#include <math.h>
#else
#define floor(d) ((double)((unsigned long long)(d)))
#endif
static double upper32(double x)
{
return floor(x*TwoToMinus32);
}
static double lower32(double x, double y)
{
return x-TwoTo32*floor(x*TwoToMinus32);
}
static double mod(double x, double oneoverm, double m)
{
return x-m*floor(x*oneoverm);
}
#endif
static void cleanup(double *dt, int from, int tlen)
{
int i;
double tmp,tmp1,x,x1;
tmp=tmp1=Zero;
/* original code **
for(i=2*from;i<2*tlen-2;i++)
{
x=dt[i];
dt[i]=lower32(x,Zero)+tmp1;
tmp1=tmp;
tmp=upper32(x);
}
dt[tlen-2]+=tmp1;
dt[tlen-1]+=tmp;
**end original code ***/
/* new code ***/
for(i=2*from;i<2*tlen;i+=2)
{
x=dt[i];
x1=dt[i+1];
dt[i]=lower32(x,Zero)+tmp;
dt[i+1]=lower32(x1,Zero)+tmp1;
tmp=upper32(x);
tmp1=upper32(x1);
}
/** end new code **/
}
void conv_d16_to_i32(unsigned int *i32, double *d16, long long *tmp, int ilen)
{
int i;
long long t, t1, a, b, c, d;
t1=0;
a=(long long)d16[0];
b=(long long)d16[1];
for(i=0; i<ilen-1; i++)
{
c=(long long)d16[2*i+2];
t1+=(unsigned int)a;
t=(a>>32);
d=(long long)d16[2*i+3];
t1+=(b&0xffff)<<16;
t+=(b>>16)+(t1>>32);
i32[i]=(unsigned int)t1;
t1=t;
a=c;
b=d;
}
t1+=(unsigned int)a;
t=(a>>32);
t1+=(b&0xffff)<<16;
i32[i]=(unsigned int)t1;
}
void conv_i32_to_d32(double *d32, unsigned int *i32, int len)
{
int i;
#pragma pipeloop(0)
for(i=0;i<len;i++) d32[i]=(double)(i32[i]);
}
void conv_i32_to_d16(double *d16, unsigned int *i32, int len)
{
int i;
unsigned int a;
#pragma pipeloop(0)
for(i=0;i<len;i++)
{
a=i32[i];
d16[2*i]=(double)(a&0xffff);
d16[2*i+1]=(double)(a>>16);
}
}
void conv_i32_to_d32_and_d16(double *d32, double *d16,
unsigned int *i32, int len)
{
int i = 0;
unsigned int a;
#pragma pipeloop(0)
#ifdef RF_INLINE_MACROS
for(;i<len-3;i+=4)
{
i16_to_d16_and_d32x4(&TwoToMinus16, &TwoTo16, &Zero,
&(d16[2*i]), &(d32[i]), (float *)(&(i32[i])));
}
#endif
for(;i<len;i++)
{
a=i32[i];
d32[i]=(double)(i32[i]);
d16[2*i]=(double)(a&0xffff);
d16[2*i+1]=(double)(a>>16);
}
}
void adjust_montf_result(unsigned int *i32, unsigned int *nint, int len)
{
long long acc;
int i;
if(i32[len]>0) i=-1;
else
{
for(i=len-1; i>=0; i--)
{
if(i32[i]!=nint[i]) break;
}
}
if((i<0)||(i32[i]>nint[i]))
{
acc=0;
for(i=0;i<len;i++)
{
acc=acc+(unsigned long long)(i32[i])-(unsigned long long)(nint[i]);
i32[i]=(unsigned int)acc;
acc=acc>>32;
}
}
}
/*
** the lengths of the input arrays should be at least the following:
** result[nlen+1], dm1[nlen], dm2[2*nlen+1], dt[4*nlen+2], dn[nlen], nint[nlen]
** all of them should be different from one another
**
*/
void mont_mulf_noconv(unsigned int *result,
double *dm1, double *dm2, double *dt,
double *dn, unsigned int *nint,
int nlen, double dn0)
{
int i, j, jj;
int tmp;
double digit, m2j, nextm2j, a, b;
double *dptmp, *pdm1, *pdm2, *pdn, *pdtj, pdn_0, pdm1_0;
pdm1=&(dm1[0]);
pdm2=&(dm2[0]);
pdn=&(dn[0]);
pdm2[2*nlen]=Zero;
if (nlen!=16)
{
for(i=0;i<4*nlen+2;i++) dt[i]=Zero;
a=dt[0]=pdm1[0]*pdm2[0];
digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16);
pdtj=&(dt[0]);
for(j=jj=0;j<2*nlen;j++,jj++,pdtj++)
{
m2j=pdm2[j];
a=pdtj[0]+pdn[0]*digit;
b=pdtj[1]+pdm1[0]*pdm2[j+1]+a*TwoToMinus16;
pdtj[1]=b;
#pragma pipeloop(0)
for(i=1;i<nlen;i++)
{
pdtj[2*i]+=pdm1[i]*m2j+pdn[i]*digit;
}
if((jj==30)) {cleanup(dt,j/2+1,2*nlen+1); jj=0;}
digit=mod(lower32(b,Zero)*dn0,TwoToMinus16,TwoTo16);
}
}
else
{
a=dt[0]=pdm1[0]*pdm2[0];
dt[65]= dt[64]= dt[63]= dt[62]= dt[61]= dt[60]=
dt[59]= dt[58]= dt[57]= dt[56]= dt[55]= dt[54]=
dt[53]= dt[52]= dt[51]= dt[50]= dt[49]= dt[48]=
dt[47]= dt[46]= dt[45]= dt[44]= dt[43]= dt[42]=
dt[41]= dt[40]= dt[39]= dt[38]= dt[37]= dt[36]=
dt[35]= dt[34]= dt[33]= dt[32]= dt[31]= dt[30]=
dt[29]= dt[28]= dt[27]= dt[26]= dt[25]= dt[24]=
dt[23]= dt[22]= dt[21]= dt[20]= dt[19]= dt[18]=
dt[17]= dt[16]= dt[15]= dt[14]= dt[13]= dt[12]=
dt[11]= dt[10]= dt[ 9]= dt[ 8]= dt[ 7]= dt[ 6]=
dt[ 5]= dt[ 4]= dt[ 3]= dt[ 2]= dt[ 1]=Zero;
pdn_0=pdn[0];
pdm1_0=pdm1[0];
digit=mod(lower32(a,Zero)*dn0,TwoToMinus16,TwoTo16);
pdtj=&(dt[0]);
for(j=0;j<32;j++,pdtj++)
{
m2j=pdm2[j];
a=pdtj[0]+pdn_0*digit;
b=pdtj[1]+pdm1_0*pdm2[j+1]+a*TwoToMinus16;
pdtj[1]=b;
/**** this loop will be fully unrolled:
for(i=1;i<16;i++)
{
pdtj[2*i]+=pdm1[i]*m2j+pdn[i]*digit;
}
*************************************/
pdtj[2]+=pdm1[1]*m2j+pdn[1]*digit;
pdtj[4]+=pdm1[2]*m2j+pdn[2]*digit;
pdtj[6]+=pdm1[3]*m2j+pdn[3]*digit;
pdtj[8]+=pdm1[4]*m2j+pdn[4]*digit;
pdtj[10]+=pdm1[5]*m2j+pdn[5]*digit;
pdtj[12]+=pdm1[6]*m2j+pdn[6]*digit;
pdtj[14]+=pdm1[7]*m2j+pdn[7]*digit;
pdtj[16]+=pdm1[8]*m2j+pdn[8]*digit;
pdtj[18]+=pdm1[9]*m2j+pdn[9]*digit;
pdtj[20]+=pdm1[10]*m2j+pdn[10]*digit;
pdtj[22]+=pdm1[11]*m2j+pdn[11]*digit;
pdtj[24]+=pdm1[12]*m2j+pdn[12]*digit;
pdtj[26]+=pdm1[13]*m2j+pdn[13]*digit;
pdtj[28]+=pdm1[14]*m2j+pdn[14]*digit;
pdtj[30]+=pdm1[15]*m2j+pdn[15]*digit;
/* no need for cleenup, cannot overflow */
digit=mod(lower32(b,Zero)*dn0,TwoToMinus16,TwoTo16);
}
}
conv_d16_to_i32(result,dt+2*nlen,(long long *)dt,nlen+1);
adjust_montf_result(result,nint,nlen);
}

View File

@@ -1,103 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is interface file for SPARC Montgomery multiply functions.
*
* The Initial Developer of the Original Code is
* Sun Microsystems Inc.
* Portions created by the Initial Developer are Copyright (C) 1999-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Netscape Communications Corporation
*
* 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: montmulf.h,v 1.4 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
/* The functions that are to be called from outside of the .s file have the
* following interfaces and array size requirements:
*/
void conv_i32_to_d32(double *d32, unsigned int *i32, int len);
/* Converts an array of int's to an array of doubles, so that each double
* corresponds to an int. len is the number of items converted.
* Does not allocate the output array.
* The pointers d32 and i32 should point to arrays of size at least len
* (doubles and unsigned ints, respectively)
*/
void conv_i32_to_d16(double *d16, unsigned int *i32, int len);
/* Converts an array of int's to an array of doubles so that each element
* of the int array is converted to a pair of doubles, the first one
* corresponding to the lower (least significant) 16 bits of the int and
* the second one corresponding to the upper (most significant) 16 bits of
* the 32-bit int. len is the number of ints converted.
* Does not allocate the output array.
* The pointer d16 should point to an array of doubles of size at least
* 2*len and i32 should point an array of ints of size at least len
*/
void conv_i32_to_d32_and_d16(double *d32, double *d16,
unsigned int *i32, int len);
/* Does the above two conversions together, it is much faster than doing
* both of those in succession
*/
void mont_mulf_noconv(unsigned int *result,
double *dm1, double *dm2, double *dt,
double *dn, unsigned int *nint,
int nlen, double dn0);
/* Does the Montgomery multiplication of the numbers stored in the arrays
* pointed to by dm1 and dm2, writing the result to the array pointed to by
* result. It uses the array pointed to by dt as a temporary work area.
* nint should point to the modulus in the array-of-integers representation,
* dn should point to its array-of-doubles as obtained as a result of the
* function call conv_i32_to_d32(dn, nint, nlen);
* nlen is the length of the array containing the modulus.
* The representation used for dm1 is the one that is a result of the function
* call conv_i32_to_d32(dm1, m1, nlen), the representation for dm2 is the
* result of the function call conv_i32_to_d16(dm2, m2, nlen).
* Note that m1 and m2 should both be of length nlen, so they should be
* padded with 0's if necessary before the conversion. The result comes in
* this form (int representation, padded with 0's).
* dn0 is the value of the 16 least significant bits of n0'.
* The function does not allocate memory for any of the arrays, so the
* pointers should point to arrays with the following minimal sizes:
* result - nlen+1
* dm1 - nlen
* dm2 - 2*nlen+1 ( the +1 is necessary for technical reasons )
* dt - 4*nlen+2
* dn - nlen
* nint - nlen
* No two arrays should point to overlapping areas of memory.
*/

View File

@@ -1,141 +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 inline macros for SPARC Montgomery multiply functions.
!
! The Initial Developer of the Original Code is
! Sun Microsystems Inc.
! Portions created by the Initial Developer are Copyright (C) 1999-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: montmulf.il,v 1.4 2004-04-27 23:04:36 gerv%gerv.net Exp $
!
! double upper32(double /*frs1*/);
!
.inline upper32,8
std %o0,[%sp+0x48]
ldd [%sp+0x48],%f10
fdtox %f10,%f10
fitod %f10,%f0
.end
!
! double lower32(double /*frs1*/, double /* Zero */);
!
.inline lower32,8
std %o0,[%sp+0x48]
ldd [%sp+0x48],%f10
std %o2,[%sp+0x48]
ldd [%sp+0x48],%f12
fdtox %f10,%f10
fmovs %f12,%f10
fxtod %f10,%f0
.end
!
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
!
.inline mod,12
std %o0,[%sp+0x48]
ldd [%sp+0x48],%f2
std %o2,[%sp+0x48]
ldd [%sp+0x48],%f4
std %o4,[%sp+0x48]
ldd [%sp+0x48],%f6
fmuld %f2,%f4,%f4
fdtox %f4,%f4
fxtod %f4,%f4
fmuld %f4,%f6,%f4
fsubd %f2,%f4,%f0
.end
!
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
! double * /* 0 */,
! double * /*result16*/, double * /* result32 */
! float * /*source - should be unsigned int*
! converted to float* */);
!
.inline i16_to_d16_and_d32x4,24
ldd [%o0],%f2 ! 1/(2^16)
ldd [%o1],%f4 ! 2^16
ldd [%o2],%f22
fmovd %f22,%f6
ld [%o5],%f7
fmovd %f22,%f10
ld [%o5+4],%f11
fmovd %f22,%f14
ld [%o5+8],%f15
fmovd %f22,%f18
ld [%o5+12],%f19
fxtod %f6,%f6
std %f6,[%o4]
fxtod %f10,%f10
std %f10,[%o4+8]
fxtod %f14,%f14
std %f14,[%o4+16]
fxtod %f18,%f18
std %f18,[%o4+24]
fmuld %f2,%f6,%f8
fmuld %f2,%f10,%f12
fmuld %f2,%f14,%f16
fmuld %f2,%f18,%f20
fdtox %f8,%f8
fdtox %f12,%f12
fdtox %f16,%f16
fdtox %f20,%f20
fxtod %f8,%f8
std %f8,[%o3+8]
fxtod %f12,%f12
std %f12,[%o3+24]
fxtod %f16,%f16
std %f16,[%o3+40]
fxtod %f20,%f20
std %f20,[%o3+56]
fmuld %f8,%f4,%f8
fmuld %f12,%f4,%f12
fmuld %f16,%f4,%f16
fmuld %f20,%f4,%f20
fsubd %f6,%f8,%f8
std %f8,[%o3]
fsubd %f10,%f12,%f12
std %f12,[%o3+16]
fsubd %f14,%f16,%f16
std %f16,[%o3+32]
fsubd %f18,%f20,%f20
std %f20,[%o3+48]
.end

File diff suppressed because it is too large Load Diff

View File

@@ -1,141 +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 inline macros for SPARC Montgomery multiply functions.
!
! The Initial Developer of the Original Code is
! Sun Microsystems Inc.
! Portions created by the Initial Developer are Copyright (C) 1999-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: montmulfv8.il,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $
!
! double upper32(double /*frs1*/);
!
.inline upper32,8
std %o0,[%sp+0x48]
ldd [%sp+0x48],%f10
fdtox %f10,%f10
fitod %f10,%f0
.end
!
! double lower32(double /*frs1*/, double /* Zero */);
!
.inline lower32,8
std %o0,[%sp+0x48]
ldd [%sp+0x48],%f10
std %o2,[%sp+0x48]
ldd [%sp+0x48],%f12
fdtox %f10,%f10
fmovs %f12,%f10
fxtod %f10,%f0
.end
!
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
!
.inline mod,12
std %o0,[%sp+0x48]
ldd [%sp+0x48],%f2
std %o2,[%sp+0x48]
ldd [%sp+0x48],%f4
std %o4,[%sp+0x48]
ldd [%sp+0x48],%f6
fmuld %f2,%f4,%f4
fdtox %f4,%f4
fxtod %f4,%f4
fmuld %f4,%f6,%f4
fsubd %f2,%f4,%f0
.end
!
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
! double * /* 0 */,
! double * /*result16*/, double * /* result32 */
! float * /*source - should be unsigned int*
! converted to float* */);
!
.inline i16_to_d16_and_d32x4,24
ldd [%o0],%f2 ! 1/(2^16)
ldd [%o1],%f4 ! 2^16
ldd [%o2],%f22
fmovd %f22,%f6
ld [%o5],%f7
fmovd %f22,%f10
ld [%o5+4],%f11
fmovd %f22,%f14
ld [%o5+8],%f15
fmovd %f22,%f18
ld [%o5+12],%f19
fxtod %f6,%f6
std %f6,[%o4]
fxtod %f10,%f10
std %f10,[%o4+8]
fxtod %f14,%f14
std %f14,[%o4+16]
fxtod %f18,%f18
std %f18,[%o4+24]
fmuld %f2,%f6,%f8
fmuld %f2,%f10,%f12
fmuld %f2,%f14,%f16
fmuld %f2,%f18,%f20
fdtox %f8,%f8
fdtox %f12,%f12
fdtox %f16,%f16
fdtox %f20,%f20
fxtod %f8,%f8
std %f8,[%o3+8]
fxtod %f12,%f12
std %f12,[%o3+24]
fxtod %f16,%f16
std %f16,[%o3+40]
fxtod %f20,%f20
std %f20,[%o3+56]
fmuld %f8,%f4,%f8
fmuld %f12,%f4,%f12
fmuld %f16,%f4,%f16
fmuld %f20,%f4,%f20
fsubd %f6,%f8,%f8
std %f8,[%o3]
fsubd %f10,%f12,%f12
std %f12,[%o3+16]
fsubd %f14,%f16,%f16
std %f16,[%o3+32]
fsubd %f18,%f20,%f20
std %f20,[%o3+48]
.end

File diff suppressed because it is too large Load Diff

View File

@@ -1,126 +0,0 @@
!
! ***** BEGIN LICENSE BLOCK *****
! Version: MPL 1.1/GPL 2.0/LGPL 2.1
!
! The contents of this file are subject to the Mozilla Public License Version
! 1.1 (the "License"); you may not use this file except in compliance with
! the License. You may obtain a copy of the License at
! http://www.mozilla.org/MPL/
!
! Software distributed under the License is distributed on an "AS IS" basis,
! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
! for the specific language governing rights and limitations under the
! License.
!
! The Original Code is inline macros for SPARC Montgomery multiply functions.
!
! The Initial Developer of the Original Code is
! Sun Microsystems Inc.
! Portions created by the Initial Developer are Copyright (C) 1999-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: montmulfv9.il,v 1.3 2004-04-27 23:04:36 gerv%gerv.net Exp $
!
! double upper32(double /*frs1*/);
!
.inline upper32,8
fdtox %f0,%f10
fitod %f10,%f0
.end
!
! double lower32(double /*frs1*/, double /* Zero */);
!
.inline lower32,8
fdtox %f0,%f10
fmovs %f2,%f10
fxtod %f10,%f0
.end
!
! double mod(double /*x*/, double /*1/m*/, double /*m*/);
!
.inline mod,12
fmuld %f0,%f2,%f2
fdtox %f2,%f2
fxtod %f2,%f2
fmuld %f2,%f4,%f2
fsubd %f0,%f2,%f0
.end
!
! void i16_to_d16_and_d32x4(double * /*1/(2^16)*/, double * /* 2^16*/,
! double * /* 0 */,
! double * /*result16*/, double * /* result32 */
! float * /*source - should be unsigned int*
! converted to float* */);
!
.inline i16_to_d16_and_d32x4,24
ldd [%o0],%f2 ! 1/(2^16)
ldd [%o1],%f4 ! 2^16
ldd [%o2],%f22
fmovd %f22,%f6
ld [%o5],%f7
fmovd %f22,%f10
ld [%o5+4],%f11
fmovd %f22,%f14
ld [%o5+8],%f15
fmovd %f22,%f18
ld [%o5+12],%f19
fxtod %f6,%f6
std %f6,[%o4]
fxtod %f10,%f10
std %f10,[%o4+8]
fxtod %f14,%f14
std %f14,[%o4+16]
fxtod %f18,%f18
std %f18,[%o4+24]
fmuld %f2,%f6,%f8
fmuld %f2,%f10,%f12
fmuld %f2,%f14,%f16
fmuld %f2,%f18,%f20
fdtox %f8,%f8
fdtox %f12,%f12
fdtox %f16,%f16
fdtox %f20,%f20
fxtod %f8,%f8
std %f8,[%o3+8]
fxtod %f12,%f12
std %f12,[%o3+24]
fxtod %f16,%f16
std %f16,[%o3+40]
fxtod %f20,%f20
std %f20,[%o3+56]
fmuld %f8,%f4,%f8
fmuld %f12,%f4,%f12
fmuld %f16,%f4,%f16
fmuld %f20,%f4,%f20
fsubd %f6,%f8,%f8
std %f8,[%o3]
fsubd %f10,%f12,%f12
std %f12,[%o3+16]
fsubd %f14,%f16,%f16
std %f16,[%o3+32]
fsubd %f18,%f20,%f20
std %f20,[%o3+48]
.end

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +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 Multi-precision Binary Polynomial Arithmetic 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):
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
* Douglas Stebila <douglas@stebila.ca> of Sun 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 _MP_GF2M_PRIV_H_
#define _MP_GF2M_PRIV_H_
#include "mpi-priv.h"
extern const mp_digit mp_gf2m_sqr_tb[16];
#if defined(MP_USE_UINT_DIGIT)
#define MP_DIGIT_BITS 32
#else
#define MP_DIGIT_BITS 64
#endif
/* Platform-specific macros for fast binary polynomial squaring. */
#if MP_DIGIT_BITS == 32
#define gf2m_SQR1(w) \
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 16 | \
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF]
#define gf2m_SQR0(w) \
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
#else
#define gf2m_SQR1(w) \
mp_gf2m_sqr_tb[(w) >> 60 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 56 & 0xF] << 48 | \
mp_gf2m_sqr_tb[(w) >> 52 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 48 & 0xF] << 32 | \
mp_gf2m_sqr_tb[(w) >> 44 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 40 & 0xF] << 16 | \
mp_gf2m_sqr_tb[(w) >> 36 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 32 & 0xF]
#define gf2m_SQR0(w) \
mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 48 | \
mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] << 32 | \
mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \
mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF]
#endif
/* Multiply two binary polynomials mp_digits a, b.
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
* Output in two mp_digits rh, rl.
*/
void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b);
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
* result is a binary polynomial in 4 mp_digits r[4].
* The caller MUST ensure that r has the right amount of space allocated.
*/
void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
const mp_digit b0);
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
* result is a binary polynomial in 6 mp_digits r[6].
* The caller MUST ensure that r has the right amount of space allocated.
*/
void s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
const mp_digit b2, const mp_digit b1, const mp_digit b0);
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
* result is a binary polynomial in 8 mp_digits r[8].
* The caller MUST ensure that r has the right amount of space allocated.
*/
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
const mp_digit b0);
#endif /* _MP_GF2M_PRIV_H_ */

View File

@@ -1,600 +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 Multi-precision Binary Polynomial Arithmetic 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):
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
* Douglas Stebila <douglas@stebila.ca> of Sun 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 "mp_gf2m.h"
#include "mp_gf2m-priv.h"
#include "mplogic.h"
#include "mpi-priv.h"
const mp_digit mp_gf2m_sqr_tb[16] =
{
0, 1, 4, 5, 16, 17, 20, 21,
64, 65, 68, 69, 80, 81, 84, 85
};
/* Multiply two binary polynomials mp_digits a, b.
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.
* Output in two mp_digits rh, rl.
*/
#if MP_DIGIT_BITS == 32
void
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
{
register mp_digit h, l, s;
mp_digit tab[8], top2b = a >> 30;
register mp_digit a1, a2, a4;
a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
s = tab[b & 0x7]; l = s;
s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29;
s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26;
s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23;
s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8;
s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5;
s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2;
/* compensate for the top two bits of a */
if (top2b & 01) { l ^= b << 30; h ^= b >> 2; }
if (top2b & 02) { l ^= b << 31; h ^= b >> 1; }
*rh = h; *rl = l;
}
#else
void
s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b)
{
register mp_digit h, l, s;
mp_digit tab[16], top3b = a >> 61;
register mp_digit a1, a2, a4, a8;
a1 = a & (0x1FFFFFFFFFFFFFFF); a2 = a1 << 1;
a4 = a2 << 1; a8 = a4 << 1;
tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2;
tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4;
tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8;
tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
s = tab[b & 0xF]; l = s;
s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60;
s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56;
s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8;
s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4;
/* compensate for the top three bits of a */
if (top3b & 01) { l ^= b << 61; h ^= b >> 3; }
if (top3b & 02) { l ^= b << 62; h ^= b >> 2; }
if (top3b & 04) { l ^= b << 63; h ^= b >> 1; }
*rh = h; *rl = l;
}
#endif
/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0)
* result is a binary polynomial in 4 mp_digits r[4].
* The caller MUST ensure that r has the right amount of space allocated.
*/
void
s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1,
const mp_digit b0)
{
mp_digit m1, m0;
/* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
s_bmul_1x1(r+3, r+2, a1, b1);
s_bmul_1x1(r+1, r, a0, b0);
s_bmul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1);
/* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */
r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */
r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */
}
/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0)
* result is a binary polynomial in 6 mp_digits r[6].
* The caller MUST ensure that r has the right amount of space allocated.
*/
void
s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0,
const mp_digit b2, const mp_digit b1, const mp_digit b0)
{
mp_digit zm[4];
s_bmul_1x1(r+5, r+4, a2, b2); /* fill top 2 words */
s_bmul_2x2(zm, a1, a2^a0, b1, b2^b0); /* fill middle 4 words */
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
zm[3] ^= r[3];
zm[2] ^= r[2];
zm[1] ^= r[1] ^ r[5];
zm[0] ^= r[0] ^ r[4];
r[5] ^= zm[3];
r[4] ^= zm[2];
r[3] ^= zm[1];
r[2] ^= zm[0];
}
/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0)
* result is a binary polynomial in 8 mp_digits r[8].
* The caller MUST ensure that r has the right amount of space allocated.
*/
void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
const mp_digit b0)
{
mp_digit zm[4];
s_bmul_2x2(r+4, a3, a2, b3, b2); /* fill top 4 words */
s_bmul_2x2(zm, a3^a1, a2^a0, b3^b1, b2^b0); /* fill middle 4 words */
s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */
zm[3] ^= r[3] ^ r[7];
zm[2] ^= r[2] ^ r[6];
zm[1] ^= r[1] ^ r[5];
zm[0] ^= r[0] ^ r[4];
r[5] ^= zm[3];
r[4] ^= zm[2];
r[3] ^= zm[1];
r[2] ^= zm[0];
}
/* Compute addition of two binary polynomials a and b,
* store result in c; c could be a or b, a and b could be equal;
* c is the bitwise XOR of a and b.
*/
mp_err
mp_badd(const mp_int *a, const mp_int *b, mp_int *c)
{
mp_digit *pa, *pb, *pc;
mp_size ix;
mp_size used_pa, used_pb;
mp_err res = MP_OKAY;
/* Add all digits up to the precision of b. If b had more
* precision than a initially, swap a, b first
*/
if (MP_USED(a) >= MP_USED(b)) {
pa = MP_DIGITS(a);
pb = MP_DIGITS(b);
used_pa = MP_USED(a);
used_pb = MP_USED(b);
} else {
pa = MP_DIGITS(b);
pb = MP_DIGITS(a);
used_pa = MP_USED(b);
used_pb = MP_USED(a);
}
/* Make sure c has enough precision for the output value */
MP_CHECKOK( s_mp_pad(c, used_pa) );
/* Do word-by-word xor */
pc = MP_DIGITS(c);
for (ix = 0; ix < used_pb; ix++) {
(*pc++) = (*pa++) ^ (*pb++);
}
/* Finish the rest of digits until we're actually done */
for (; ix < used_pa; ++ix) {
*pc++ = *pa++;
}
MP_USED(c) = used_pa;
MP_SIGN(c) = ZPOS;
s_mp_clamp(c);
CLEANUP:
return res;
}
#define s_mp_div2(a) MP_CHECKOK( mpl_rsh((a), (a), 1) );
/* Compute binary polynomial multiply d = a * b */
static void
s_bmul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
{
mp_digit a_i, a0b0, a1b1, carry = 0;
while (a_len--) {
a_i = *a++;
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
*d++ = a0b0 ^ carry;
carry = a1b1;
}
*d = carry;
}
/* Compute binary polynomial xor multiply accumulate d ^= a * b */
static void
s_bmul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
{
mp_digit a_i, a0b0, a1b1, carry = 0;
while (a_len--) {
a_i = *a++;
s_bmul_1x1(&a1b1, &a0b0, a_i, b);
*d++ ^= a0b0 ^ carry;
carry = a1b1;
}
*d ^= carry;
}
/* Compute binary polynomial xor multiply c = a * b.
* All parameters may be identical.
*/
mp_err
mp_bmul(const mp_int *a, const mp_int *b, mp_int *c)
{
mp_digit *pb, b_i;
mp_int tmp;
mp_size ib, a_used, b_used;
mp_err res = MP_OKAY;
MP_DIGITS(&tmp) = 0;
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
if (a == c) {
MP_CHECKOK( mp_init_copy(&tmp, a) );
if (a == b)
b = &tmp;
a = &tmp;
} else if (b == c) {
MP_CHECKOK( mp_init_copy(&tmp, b) );
b = &tmp;
}
if (MP_USED(a) < MP_USED(b)) {
const mp_int *xch = b; /* switch a and b if b longer */
b = a;
a = xch;
}
MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
MP_CHECKOK( s_mp_pad(c, USED(a) + USED(b)) );
pb = MP_DIGITS(b);
s_bmul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
/* Outer loop: Digits of b */
a_used = MP_USED(a);
b_used = MP_USED(b);
MP_USED(c) = a_used + b_used;
for (ib = 1; ib < b_used; ib++) {
b_i = *pb++;
/* Inner product: Digits of a */
if (b_i)
s_bmul_d_add(MP_DIGITS(a), a_used, b_i, MP_DIGITS(c) + ib);
else
MP_DIGIT(c, ib + a_used) = b_i;
}
s_mp_clamp(c);
SIGN(c) = ZPOS;
CLEANUP:
mp_clear(&tmp);
return res;
}
/* Compute modular reduction of a and store result in r.
* r could be a.
* For modular arithmetic, the irreducible polynomial f(t) is represented
* as an array of int[], where f(t) is of the form:
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
* where m = p[0] > p[1] > ... > p[k] = 0.
*/
mp_err
mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r)
{
int j, k;
int n, dN, d0, d1;
mp_digit zz, *z, tmp;
mp_size used;
mp_err res = MP_OKAY;
/* The algorithm does the reduction in place in r,
* if a != r, copy a into r first so reduction can be done in r
*/
if (a != r) {
MP_CHECKOK( mp_copy(a, r) );
}
z = MP_DIGITS(r);
/* start reduction */
dN = p[0] / MP_DIGIT_BITS;
used = MP_USED(r);
for (j = used - 1; j > dN;) {
zz = z[j];
if (zz == 0) {
j--; continue;
}
z[j] = 0;
for (k = 1; p[k] > 0; k++) {
/* reducing component t^p[k] */
n = p[0] - p[k];
d0 = n % MP_DIGIT_BITS;
d1 = MP_DIGIT_BITS - d0;
n /= MP_DIGIT_BITS;
z[j-n] ^= (zz>>d0);
if (d0)
z[j-n-1] ^= (zz<<d1);
}
/* reducing component t^0 */
n = dN;
d0 = p[0] % MP_DIGIT_BITS;
d1 = MP_DIGIT_BITS - d0;
z[j-n] ^= (zz >> d0);
if (d0)
z[j-n-1] ^= (zz << d1);
}
/* final round of reduction */
while (j == dN) {
d0 = p[0] % MP_DIGIT_BITS;
zz = z[dN] >> d0;
if (zz == 0) break;
d1 = MP_DIGIT_BITS - d0;
/* clear up the top d1 bits */
if (d0) z[dN] = (z[dN] << d1) >> d1;
*z ^= zz; /* reduction t^0 component */
for (k = 1; p[k] > 0; k++) {
/* reducing component t^p[k]*/
n = p[k] / MP_DIGIT_BITS;
d0 = p[k] % MP_DIGIT_BITS;
d1 = MP_DIGIT_BITS - d0;
z[n] ^= (zz << d0);
tmp = zz >> d1;
if (d0 && tmp)
z[n+1] ^= tmp;
}
}
s_mp_clamp(r);
CLEANUP:
return res;
}
/* Compute the product of two polynomials a and b, reduce modulo p,
* Store the result in r. r could be a or b; a could be b.
*/
mp_err
mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[], mp_int *r)
{
mp_err res;
if (a == b) return mp_bsqrmod(a, p, r);
if ((res = mp_bmul(a, b, r) ) != MP_OKAY)
return res;
return mp_bmod(r, p, r);
}
/* Compute binary polynomial squaring c = a*a mod p .
* Parameter r and a can be identical.
*/
mp_err
mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r)
{
mp_digit *pa, *pr, a_i;
mp_int tmp;
mp_size ia, a_used;
mp_err res;
ARGCHK(a != NULL && r != NULL, MP_BADARG);
MP_DIGITS(&tmp) = 0;
if (a == r) {
MP_CHECKOK( mp_init_copy(&tmp, a) );
a = &tmp;
}
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
MP_CHECKOK( s_mp_pad(r, 2*USED(a)) );
pa = MP_DIGITS(a);
pr = MP_DIGITS(r);
a_used = MP_USED(a);
MP_USED(r) = 2 * a_used;
for (ia = 0; ia < a_used; ia++) {
a_i = *pa++;
*pr++ = gf2m_SQR0(a_i);
*pr++ = gf2m_SQR1(a_i);
}
MP_CHECKOK( mp_bmod(r, p, r) );
s_mp_clamp(r);
SIGN(r) = ZPOS;
CLEANUP:
mp_clear(&tmp);
return res;
}
/* Compute binary polynomial y/x mod p, y divided by x, reduce modulo p.
* Store the result in r. r could be x or y, and x could equal y.
* Uses algorithm Modular_Division_GF(2^m) from
* Chang-Shantz, S. "From Euclid's GCD to Montgomery Multiplication to
* the Great Divide".
*/
int
mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
const unsigned int p[], mp_int *r)
{
mp_int aa, bb, uu;
mp_int *a, *b, *u, *v;
mp_err res = MP_OKAY;
MP_DIGITS(&aa) = 0;
MP_DIGITS(&bb) = 0;
MP_DIGITS(&uu) = 0;
MP_CHECKOK( mp_init_copy(&aa, x) );
MP_CHECKOK( mp_init_copy(&uu, y) );
MP_CHECKOK( mp_init_copy(&bb, pp) );
MP_CHECKOK( s_mp_pad(r, USED(pp)) );
MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
a = &aa; b= &bb; u=&uu; v=r;
/* reduce x and y mod p */
MP_CHECKOK( mp_bmod(a, p, a) );
MP_CHECKOK( mp_bmod(u, p, u) );
while (!mp_isodd(a)) {
s_mp_div2(a);
if (mp_isodd(u)) {
MP_CHECKOK( mp_badd(u, pp, u) );
}
s_mp_div2(u);
}
do {
if (mp_cmp_mag(b, a) > 0) {
MP_CHECKOK( mp_badd(b, a, b) );
MP_CHECKOK( mp_badd(v, u, v) );
do {
s_mp_div2(b);
if (mp_isodd(v)) {
MP_CHECKOK( mp_badd(v, pp, v) );
}
s_mp_div2(v);
} while (!mp_isodd(b));
}
else if ((MP_DIGIT(a,0) == 1) && (MP_USED(a) == 1))
break;
else {
MP_CHECKOK( mp_badd(a, b, a) );
MP_CHECKOK( mp_badd(u, v, u) );
do {
s_mp_div2(a);
if (mp_isodd(u)) {
MP_CHECKOK( mp_badd(u, pp, u) );
}
s_mp_div2(u);
} while (!mp_isodd(a));
}
} while (1);
MP_CHECKOK( mp_copy(u, r) );
CLEANUP:
return res;
}
/* Convert the bit-string representation of a polynomial a into an array
* of integers corresponding to the bits with non-zero coefficient.
* Up to max elements of the array will be filled. Return value is total
* number of coefficients that would be extracted if array was large enough.
*/
int
mp_bpoly2arr(const mp_int *a, unsigned int p[], int max)
{
int i, j, k;
mp_digit top_bit, mask;
top_bit = 1;
top_bit <<= MP_DIGIT_BIT - 1;
for (k = 0; k < max; k++) p[k] = 0;
k = 0;
for (i = MP_USED(a) - 1; i >= 0; i--) {
mask = top_bit;
for (j = MP_DIGIT_BIT - 1; j >= 0; j--) {
if (MP_DIGITS(a)[i] & mask) {
if (k < max) p[k] = MP_DIGIT_BIT * i + j;
k++;
}
mask >>= 1;
}
}
return k;
}
/* Convert the coefficient array representation of a polynomial to a
* bit-string. The array must be terminated by 0.
*/
mp_err
mp_barr2poly(const unsigned int p[], mp_int *a)
{
mp_err res = MP_OKAY;
int i;
mp_zero(a);
for (i = 0; p[i] > 0; i++) {
MP_CHECKOK( mpl_set_bit(a, p[i], 1) );
}
MP_CHECKOK( mpl_set_bit(a, 0, 1) );
CLEANUP:
return res;
}

View File

@@ -1,63 +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 Multi-precision Binary Polynomial Arithmetic 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):
* Sheueling Chang Shantz <sheueling.chang@sun.com> and
* Douglas Stebila <douglas@stebila.ca> of Sun 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 _MP_GF2M_H_
#define _MP_GF2M_H_
#include "mpi.h"
mp_err mp_badd(const mp_int *a, const mp_int *b, mp_int *c);
mp_err mp_bmul(const mp_int *a, const mp_int *b, mp_int *c);
/* For modular arithmetic, the irreducible polynomial f(t) is represented
* as an array of int[], where f(t) is of the form:
* f(t) = t^p[0] + t^p[1] + ... + t^p[k]
* where m = p[0] > p[1] > ... > p[k] = 0.
*/
mp_err mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r);
mp_err mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[],
mp_int *r);
mp_err mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r);
mp_err mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
const unsigned int p[], mp_int *r);
int mp_bpoly2arr(const mp_int *a, unsigned int p[], int max);
mp_err mp_barr2poly(const unsigned int p[], mp_int *a);
#endif /* _MP_GF2M_H_ */

View File

@@ -1,760 +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
* Red Hat, Inc
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Relyea <rrelyea@redhat.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 "mpi.h"
/*
* This file implements a single function: mpi_getProcessorLineSize();
* mpi_getProcessorLineSize() returns the size in bytes of the cache line
* if a cache exists, or zero if there is no cache. If more than one
* cache line exists, it should return the smallest line size (which is
* usually the L1 cache).
*
* mp_modexp uses this information to make sure that private key information
* isn't being leaked through the cache.
*
* Currently the file returns good data for most modern x86 processors, and
* reasonable data on 64-bit ppc processors. All other processors are assumed
* to have a cache line size of 32 bytes unless modified by target.mk.
*
*/
#if defined(i386) || defined(__i386) || defined(__X86__) || defined (_M_IX86)
/* X86 processors have special instructions that tell us about the cache */
#include "string.h"
/* Generic CPUID function */
#ifndef _WIN32
static void cpuid(unsigned long op, unsigned long *eax,
unsigned long *ebx, unsigned long *ecx,
unsigned long *edx)
{
/* sigh GCC isn't smart enough to save the ebx PIC register on it's own
* in this case, so do it by hand. */
__asm__("pushl %%ebx\n\t"
"cpuid\n\t"
"mov %%ebx,%1\n\t"
"popl %%ebx\n\t"
: "=a" (*eax),
"=r" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "0" (op));
}
/*
* try flipping a processor flag to determine CPU type
*/
static unsigned long changeFlag(unsigned long flag)
{
unsigned long changedFlags, originalFlags;
__asm__("pushfl\n\t" /* get the flags */
"popl %0\n\t"
"movl %0,%1\n\t" /* save the original flags */
"xor %0,%2\n\t" /* flip the but */
"pushl %0\n\t" /* set the flags */
"popfl\n\t"
"pushfl\n\t" /* get the flags again (for return) */
"popl %0\n\t"
"pushl %1\n\t" /* restore the original flags */
"popfl\n\t"
: "=r" (changedFlags),
"=r" (originalFlags)
: "r" (flag));
return changedFlags ^ originalFlags;
}
#else
/*
* windows versions of the above assembler
*/
#define wcpuid __asm __emit 0fh __asm __emit 0a2h
static void cpuid(unsigned long op, unsigned long *Reax, unsigned long *Rebx,
unsigned long *Recx, unsigned long *Redx)
{
unsigned long Leax, Lebx, Lecx, Ledx;
__asm {
pushad
mov eax,op
wcpuid
mov Leax,eax
mov Lebx,ebx
mov Lecx,ecx
mov Ledx,edx
popad
}
*Reax = Leax;
*Rebx = Lebx;
*Recx = Lecx;
*Redx = Ledx;
}
static unsigned long changeFlag(unsigned long flag)
{
unsigned long changedFlags, originalFlags;
__asm {
pushad
pushfd /* get the flags */
pop eax
mov ecx,eax /* save the original flags */
mov originalFlags,ecx /* save the original flags */
mov ebx,flag
xor eax,ebx /* flip the but */
push eax /* set the flags */
popfd
pushfd /* get the flags again (for return) */
pop eax
push ecx /* restore the original flags */
popfd
mov changedFlags,eax
popad
}
return changedFlags ^ originalFlags;
}
#endif
#define AC_FLAG 0x40000
#define ID_FLAG 0x200000
/* 386 processors can't flip the AC_FLAG, intel AP Note AP-485 */
static int is386()
{
return changeFlag(AC_FLAG) == 0;
}
/* 486 processors can't flip the ID_FLAG, intel AP Note AP-485 */
static int is486()
{
return changeFlag(ID_FLAG) == 0;
}
/*
* table for Intel Cache.
* See Intel Application Note AP-485 for more information
*/
typedef enum {
Cache_NONE = 0,
Cache_UNKNOWN = 1,
Cache_TLB = 2,
Cache_Trace = 3,
Cache_L1 = 4,
Cache_L2 = 5 ,
Cache_L3 = 6
} CacheType;
#define DATA_INSTR 1
#define DATA_DATA 2
#define DATA_BOTH 3
#define DATA_TRACE 4
#define DATA_NONE 0
#define TLB_4k 0x01
#define TLB_2M 0x08
#define TLB_4M 0x10
#define TLB_4Mk 0x11
#define TLB_ALL 0x19
#define k * 1024
#define M * (1024*1024)
#define G * (1024*1024*1024)
struct _cache {
CacheType type;
unsigned long data;
#define pageSize size
#define trcuops size
unsigned long size;
unsigned long association;
#define tlbEntries lineSize
unsigned long lineSize;
} CacheMap[] = {
/* 00 */ {Cache_NONE, DATA_NONE, 0, 0, 0 },
/* 01 */ {Cache_TLB, DATA_INSTR, TLB_4k, 4, 32 },
/* 02 */ {Cache_TLB, DATA_INSTR, TLB_4M, 0, 2 },
/* 03 */ {Cache_TLB, DATA_DATA, TLB_4k, 4, 64 },
/* 04 */ {Cache_TLB, DATA_DATA, TLB_4M, 4, 8 },
/* 05 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 06 */ {Cache_L1, DATA_INSTR, 8 k, 4, 32 },
/* 07 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 08 */ {Cache_L1, DATA_INSTR, 16 k, 4, 32 },
/* 09 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 0a */ {Cache_L1, DATA_DATA, 8 k, 4, 32 },
/* 0b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 0c */ {Cache_L1, DATA_DATA, 16 k, 4, 32 },
/* 0d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 0e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 0f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 10 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 11 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 12 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 13 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 14 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 15 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 16 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 17 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 18 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 19 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 1a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 1b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 1c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 1d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 1e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 1f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 20 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 21 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 22 */ {Cache_L3, DATA_BOTH, 512 k, 8, 64 },
/* 23 */ {Cache_L3, DATA_BOTH, 1 M, 8, 64 },
/* 24 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 25 */ {Cache_L3, DATA_BOTH, 2 M, 8, 64 },
/* 26 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 27 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 28 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 29 */ {Cache_L3, DATA_BOTH, 4 M, 8, 64 },
/* 2a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 2b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 2c */ {Cache_L1, DATA_DATA, 32 k, 8, 64 },
/* 2d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 2e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 2f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 30 */ {Cache_L1, DATA_INSTR, 32 k, 8, 64 },
/* 31 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 32 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 33 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 34 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 35 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 36 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 37 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 38 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 39 */ {Cache_L2, DATA_BOTH, 128 k, 4, 64 },
/* 3a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 3b */ {Cache_L2, DATA_BOTH, 128 k, 2, 64 },
/* 3c */ {Cache_L2, DATA_BOTH, 256 k, 4, 64 },
/* 3d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 3e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 3f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 40 */ {Cache_L2, DATA_NONE, 0, 0, 0 },
/* 41 */ {Cache_L2, DATA_BOTH, 128 k, 4, 32 },
/* 42 */ {Cache_L2, DATA_BOTH, 256 k, 4, 32 },
/* 43 */ {Cache_L2, DATA_BOTH, 512 k, 4, 32 },
/* 44 */ {Cache_L2, DATA_BOTH, 1 M, 4, 32 },
/* 45 */ {Cache_L2, DATA_BOTH, 2 M, 4, 32 },
/* 46 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 47 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 48 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 49 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 4a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 4b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 4c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 4d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 4e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 4f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 50 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 64 },
/* 51 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 128 },
/* 52 */ {Cache_TLB, DATA_INSTR, TLB_ALL, 0, 256 },
/* 53 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 54 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 55 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 56 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 57 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 58 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 59 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 5a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 5b */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 64 },
/* 5c */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 128 },
/* 5d */ {Cache_TLB, DATA_DATA, TLB_4Mk, 0, 256 },
/* 5e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 5f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 60 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 61 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 62 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 63 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 64 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 65 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 66 */ {Cache_L1, DATA_DATA, 8 k, 4, 64 },
/* 67 */ {Cache_L1, DATA_DATA, 16 k, 4, 64 },
/* 68 */ {Cache_L1, DATA_DATA, 32 k, 4, 64 },
/* 69 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 6a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 6b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 6c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 6d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 6e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 6f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 70 */ {Cache_Trace, DATA_TRACE, 12 k, 8, 1 },
/* 71 */ {Cache_Trace, DATA_TRACE, 16 k, 8, 1 },
/* 72 */ {Cache_Trace, DATA_TRACE, 32 k, 8, 1 },
/* 73 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 74 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 75 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 76 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 77 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 78 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 79 */ {Cache_L2, DATA_BOTH, 128 k, 8, 64 },
/* 7a */ {Cache_L2, DATA_BOTH, 256 k, 8, 64 },
/* 7b */ {Cache_L2, DATA_BOTH, 512 k, 8, 64 },
/* 7c */ {Cache_L2, DATA_BOTH, 1 M, 8, 64 },
/* 7d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 7e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 7f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 80 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 81 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 82 */ {Cache_L2, DATA_BOTH, 256 k, 8, 32 },
/* 83 */ {Cache_L2, DATA_BOTH, 512 k, 8, 32 },
/* 84 */ {Cache_L2, DATA_BOTH, 1 M, 8, 32 },
/* 85 */ {Cache_L2, DATA_BOTH, 2 M, 8, 32 },
/* 86 */ {Cache_L2, DATA_BOTH, 512 k, 4, 64 },
/* 87 */ {Cache_L2, DATA_BOTH, 1 M, 8, 64 },
/* 88 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 89 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 8a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 8b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 8c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 8d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 8e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 8f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 90 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 91 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 92 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 93 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 94 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 95 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 96 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 97 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 98 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 99 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 9a */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 9b */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 9c */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 9d */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 9e */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* 9f */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* a9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* aa */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ab */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ac */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ad */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ae */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* af */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b0 */ {Cache_TLB, DATA_INSTR, TLB_4k, 4, 128 },
/* b1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b3 */ {Cache_TLB, DATA_DATA, TLB_4k, 4, 128 },
/* b4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* b9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ba */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* bb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* bc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* bd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* be */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* bf */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* c9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ca */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* cb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* cc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* cd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ce */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* cf */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* d9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* da */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* db */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* dc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* dd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* de */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* df */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* e9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ea */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* eb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ec */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ed */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ee */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ef */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f0 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f1 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f2 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f3 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f4 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f5 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f6 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f7 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f8 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* f9 */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* fa */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* fb */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* fc */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* fd */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* fe */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 },
/* ff */ {Cache_UNKNOWN, DATA_NONE, 0, 0, 0 }
};
/*
* use the above table to determine the CacheEntryLineSize.
*/
static void
getIntelCacheEntryLineSize(unsigned long val, int *level,
unsigned long *lineSize)
{
CacheType type;
type = CacheMap[val].type;
/* only interested in data caches */
/* NOTE val = 0x40 is a special value that means no L2 or L3 cache.
* this data check has the side effect of rejecting that entry. If
* that wasn't the case, we could have to reject it explicitly */
if ((CacheMap[val].data & DATA_DATA) != DATA_DATA) {
return;
}
/* look at the caches, skip types we aren't interested in.
* if we already have a value for a lower level cache, skip the
* current entry */
if (type == Cache_L1) {
*level = 1;
*lineSize = CacheMap[val].lineSize;
} else if ((*level >= 2) && type == Cache_L2) {
*level = 2;
*lineSize = CacheMap[val].lineSize;
} else if ((*level >= 3) && type == Cache_L3) {
*level = 3;
*lineSize = CacheMap[val].lineSize;
}
return;
}
static void
getIntelRegisterCacheLineSize(unsigned long val,
int *level, unsigned long *lineSize)
{
getIntelCacheEntryLineSize(val >> 24 & 0xff, level, lineSize);
getIntelCacheEntryLineSize(val >> 16 & 0xff, level, lineSize);
getIntelCacheEntryLineSize(val >> 8 & 0xff, level, lineSize);
getIntelCacheEntryLineSize(val & 0xff, level, lineSize);
}
/*
* returns '0' if no recognized cache is found, or if the cache
* information is supported by this processor
*/
static unsigned long
getIntelCacheLineSize(int cpuidLevel)
{
int level = 4;
unsigned long lineSize = 0;
unsigned long eax, ebx, ecx, edx;
int repeat, count;
if (cpuidLevel < 2) {
return 0;
}
/* command '2' of the cpuid is intel's cache info call. Each byte of the
* 4 registers contain a potential descriptor for the cache. The CacheMap
* table maps the cache entry with the processor cache. Register 'al'
* contains a count value that cpuid '2' needs to be called in order to
* find all the cache descriptors. Only registers with the high bit set
* to 'zero' have valid descriptors. This code loops through all the
* required calls to cpuid '2' and passes any valid descriptors it finds
* to the getIntelRegisterCacheLineSize code, which breaks the registers
* down into their component descriptors. In the end the lineSize of the
* lowest level cache data cache is returned. */
cpuid(2, &eax, &ebx, &ecx, &edx);
repeat = eax & 0xf;
for (count = 0; count < repeat; count++) {
if ((eax & 0x80000000) == 0) {
getIntelRegisterCacheLineSize(eax & 0xffffff00, &level, &lineSize);
}
if ((ebx & 0x80000000) == 0) {
getIntelRegisterCacheLineSize(ebx, &level, &lineSize);
}
if ((ecx & 0x80000000) == 0) {
getIntelRegisterCacheLineSize(ecx, &level, &lineSize);
}
if ((edx & 0x80000000) == 0) {
getIntelRegisterCacheLineSize(edx, &level, &lineSize);
}
if (count+1 != repeat) {
cpuid(2, &eax, &ebx, &ecx, &edx);
}
}
return lineSize;
}
/*
* returns '0' if the cache info is not supported by this processor.
* This is based on the AMD extended cache commands for cpuid.
* (see "AMD Processor Recognition Application Note" Publication 20734).
* Some other processors use the identical scheme.
* (see "Processor Recognition, Transmeta Corporation").
*/
static unsigned long
getOtherCacheLineSize(unsigned long cpuidLevel)
{
unsigned long lineSize = 0;
unsigned long eax, ebx, ecx, edx;
/* get the Extended CPUID level */
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
cpuidLevel = eax;
if (cpuidLevel >= 0x80000005) {
cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
lineSize = ecx & 0xff; /* line Size, L1 Data Cache */
}
return lineSize;
}
char *manMap[] = {
#define INTEL 0
"GenuineIntel",
#define AMD 1
"AuthenticAMD",
#define CYRIX 2
"CyrixInstead",
#define CENTAUR 2
"CentaurHauls",
#define NEXGEN 3
"NexGenDriven",
#define TRANSMETA 4
"GenuineTMx86",
#define RISE 5
"RiseRiseRise",
#define UMC 6
"UMC UMC UMC ",
#define SIS 7
"Sis Sis Sis ",
#define NATIONAL 8
"Geode by NSC",
};
int n_manufacturers = sizeof(manMap)/sizeof(manMap[0]);
#define MAN_UNKNOWN 9
unsigned long
mpi_getProcessorLineSize()
{
unsigned long eax, ebx, ecx, edx;
unsigned long cpuidLevel;
unsigned long cacheLineSize = 0;
int manufacturer = MAN_UNKNOWN;
int i;
char string[65];
if (is386()) {
return 0; /* 386 had no cache */
} if (is486()) {
return 32; /* really? need more info */
}
/* Pentium, cpuid command is available */
cpuid(0, &eax, &ebx, &ecx, &edx);
cpuidLevel = eax;
*(int *)string = ebx;
*(int *)&string[4] = edx;
*(int *)&string[8] = ecx;
string[12] = 0;
manufacturer = MAN_UNKNOWN;
for (i=0; i < n_manufacturers; i++) {
if ( strcmp(manMap[i],string) == 0) {
manufacturer = i;
}
}
if (manufacturer == INTEL) {
cacheLineSize = getIntelCacheLineSize(cpuidLevel);
} else {
cacheLineSize = getOtherCacheLineSize(cpuidLevel);
}
/* doesn't support cache info based on cpuid. This means
* an old pentium class processor, which have cache lines of
* 32. If we learn differently, we can use a switch based on
* the Manufacturer id */
if (cacheLineSize == 0) {
cacheLineSize = 32;
}
return cacheLineSize;
}
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
#endif
#if defined(__ppc64__)
/*
* Sigh, The PPC has some really nice features to help us determine cache
* size, since it had lots of direct control functions to do so. The POWER
* processor even has an instruction to do this, but it was dropped in
* PowerPC. Unfortunately most of them are not available in user mode.
*
* The dcbz function would be a great way to determine cache line size except
* 1) it only works on write-back memory (it throws an exception otherwise),
* and 2) because so many mac programs 'knew' the processor cache size was
* 32 bytes, they used this instruction as a fast 'zero 32 bytes'. Now the new
* G5 processor has 128 byte cache, but dcbz only clears 32 bytes to keep
* these programs happy. dcbzl work if 64 bit instructions are supported.
* If you know 64 bit instructions are supported, and that stack is
* write-back, you can use this code.
*/
#include "memory.h"
/* clear the cache line that contains 'array' */
static inline void dcbzl(char *array)
{
register char *a asm("r2") = array;
__asm__ __volatile__( "dcbzl %0,r0" : "=r" (a): "0"(a) );
}
#define PPC_DO_ALIGN(x,y) ((char *)\
((((long long) (x))+((y)-1))&~((y)-1)))
#define PPC_MAX_LINE_SIZE 256
unsigned long
mpi_getProcessorLineSize()
{
char testArray[2*PPC_MAX_LINE_SIZE+1];
char *test;
int i;
/* align the array on a maximum line size boundary, so we
* know we are starting to clear from the first address */
test = PPC_DO_ALIGN(testArray, PPC_MAX_LINE_SIZE);
/* set all the values to 1's */
memset(test, 0xff, PPC_MAX_LINE_SIZE);
/* clear one cache block starting at 'test' */
dcbzl(test);
/* find the size of the cleared area, that's our block size */
for (i=PPC_MAX_LINE_SIZE; i != 0; i = i/2) {
if (test[i-1] == 0) {
return i;
}
}
return 0;
}
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
#endif
/*
* put other processor and platform specific cache code here
* return the smallest cache line size in bytes on the processor
* (usually the L1 cache). If the OS has a call, this would be
* a greate place to put it.
*
* If there is no cache, return 0;
*
* define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED so the generic functions
* below aren't compiled.
*
*/
/* target.mk can define LINE_SIZE if it's common for the family or OS */
#if defined(LINE_SIZE) && !defined(MPI_GET_PROCESSOR_LINE_SIZE_DEFINED)
unsigned long
mpi_getProcessorLineSize()
{
return LINE_SIZE;
}
#define MPI_GET_PROCESSER_LINE_SIZE_DEFINED 1
#endif
/* If no way to get the processor cache line size has been defined, assume
* it's 32 bytes (most common value, does not significantly impact performance
*/
#ifndef MPI_GET_PROCESSER_LINE_SIZE_DEFINED
unsigned long
mpi_getProcessorLineSize()
{
return 32;
}
#endif
#ifdef TEST_IT
#include <stdio.h>
main()
{
printf("line size = %d\n", mpi_getProcessorLineSize());
}
#endif

View File

@@ -1,112 +0,0 @@
/* Default configuration for MPI 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 MPI Arbitrary Precision Integer Arithmetic library.
*
* The Initial Developer of the Original Code is
* Michael J. Fromberger.
* Portions created by the Initial Developer are Copyright (C) 1997
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Netscape Communications Corporation
*
* 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: mpi-config.h,v 1.5 2004-04-25 15:03:10 gerv%gerv.net Exp $ */
#ifndef MPI_CONFIG_H_
#define MPI_CONFIG_H_
/*
For boolean options,
0 = no
1 = yes
Other options are documented individually.
*/
#ifndef MP_IOFUNC
#define MP_IOFUNC 0 /* include mp_print() ? */
#endif
#ifndef MP_MODARITH
#define MP_MODARITH 1 /* include modular arithmetic ? */
#endif
#ifndef MP_NUMTH
#define MP_NUMTH 1 /* include number theoretic functions? */
#endif
#ifndef MP_LOGTAB
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
#endif
#ifndef MP_MEMSET
#define MP_MEMSET 1 /* use memset() to zero buffers? */
#endif
#ifndef MP_MEMCPY
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
#endif
#ifndef MP_CRYPTO
#define MP_CRYPTO 1 /* erase memory on free? */
#endif
#ifndef MP_ARGCHK
/*
0 = no parameter checks
1 = runtime checks, continue execution and return an error to caller
2 = assertions; dump core on parameter errors
*/
#ifdef DEBUG
#define MP_ARGCHK 2 /* how to check input arguments */
#else
#define MP_ARGCHK 1 /* how to check input arguments */
#endif
#endif
#ifndef MP_DEBUG
#define MP_DEBUG 0 /* print diagnostic output? */
#endif
#ifndef MP_DEFPREC
#define MP_DEFPREC 64 /* default precision, in digits */
#endif
#ifndef MP_MACRO
#define MP_MACRO 0 /* use macros for frequent calls? */
#endif
#ifndef MP_SQUARE
#define MP_SQUARE 1 /* use separate squaring code? */
#endif
#endif /* ifndef MPI_CONFIG_H_ */

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