Compare commits

..

2 Commits

Author SHA1 Message Date
fur%netscape.com
1c43d4984f This is a copy of regalloc_code2_BRANCH from Netscape's private repository,
as it existed in January of 1998.


git-svn-id: svn://10.0.0.236/branches/regalloc_code2_BRANCH@22571 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-02 16:12:08 +00:00
(no author)
cfe021ff88 This commit was manufactured by cvs2svn to create branch
'regalloc_code2_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/regalloc_code2_BRANCH@22567 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-02 15:57:58 +00:00
446 changed files with 5324 additions and 76979 deletions

View File

@@ -0,0 +1,134 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "BitSet.h"
// Return the next bit after index set to true or -1 if none.
//
Int32 BitSet::nextOne(Int32 pos) const
{
++pos;
if (pos < 0 || Uint32(pos) >= universeSize)
return -1;
Uint32 offset = getWordOffset(pos);
Uint8 index = getBitOffset(pos);
Word* ptr = &word[offset];
Word currentWord = *ptr++ >> index;
if (currentWord != Word(0)) {
while ((currentWord & Word(1)) == 0) {
++index;
currentWord >>= 1;
}
return (offset << nBitsInWordLog2) + index;
}
Word* limit = &word[getSizeInWords(universeSize)];
while (ptr < limit) {
++offset;
currentWord = *ptr++;
if (currentWord != Word(0)) {
index = 0;
while ((currentWord & Word(1)) == 0) {
++index;
currentWord >>= 1;
}
return (offset << nBitsInWordLog2) + index;
}
}
return -1;
}
// Return the next bit after index set to false or -1 if none.
//
Int32 BitSet::nextZero(Int32 pos) const
{
++pos;
if (pos < 0 || Uint32(pos) >= universeSize)
return -1;
Uint32 offset = getWordOffset(pos);
Uint8 index = getBitOffset(pos);
Word* ptr = &word[offset];
Word currentWord = *ptr++ >> index;
if (currentWord != Word(~0)) {
for (; index < nBitsInWord; ++index) {
if ((currentWord & Word(1)) == 0) {
Int32 ret = (offset << nBitsInWordLog2) + index;
return (Uint32(ret) < universeSize) ? ret : -1;
}
currentWord >>= 1;
}
}
Word* limit = &word[getSizeInWords(universeSize)];
while (ptr < limit) {
++offset;
currentWord = *ptr++;
if (currentWord != Word(~0)) {
for (index = 0; index < nBitsInWord; ++index) {
if ((currentWord & Word(1)) == 0) {
Int32 ret = (offset << nBitsInWordLog2) + index;
return (Uint32(ret) < universeSize) ? ret : -1;
}
currentWord >>= 1;
}
}
}
return -1;
}
#ifdef DEBUG_LOG
// Print the set.
//
void BitSet::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
Int32 currentBit = i;
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
Int32 nextBit = nextOne(currentBit);
if (nextBit != currentBit + 1) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
continue;
}
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
currentBit = nextBit;
nextBit = nextOne(nextBit);
}
if (currentBit > (i+1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
else
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
i = currentBit;
}
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,195 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _BITSET_H_
#define _BITSET_H_
#include "Fundamentals.h"
#include "LogModule.h"
#include "Pool.h"
#include <string.h>
//------------------------------------------------------------------------------
// BitSet -
class BitSet
{
private:
#if (PR_BITS_PER_WORD == 64)
typedef Uint64 Word;
#elif (PR_BITS_PER_WORD == 32)
typedef Uint32 Word;
#endif
static const nBitsInWord = PR_BITS_PER_WORD;
static const nBytesInWord = PR_BYTES_PER_WORD;
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
// Return the number of Word need to store the universe.
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
// Return the given element offset in its containing Word.
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
// Return the Word offset for the given element int the universe.
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
// Return the mask for the given bit index.
static Word getMask(Uint8 index) {return Word(1) << index;}
private:
Uint32 universeSize; // Size of the universe
Word* word; // universe memory.
private:
// No copy constructor.
BitSet(const BitSet&);
// Check if the given set's universe is of the same size than this universe.
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
// Check if pos is valid for this set's universe.
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
public:
// Create a bitset of universeSize bits.
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
// Return the size of this bitset.
Uint32 getSize() const {return universeSize;}
// Clear the bitset.
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
// Clear the bit at index.
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
// Set the bitset.
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
// Set the bit at index.
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
// Return true if the bit at index is set.
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
// Union with the given bitset.
inline void or(const BitSet& set);
// Intersection with the given bitset.
inline void and(const BitSet& set);
// Difference with the given bitset.
inline void difference(const BitSet& set);
// Copy set.
inline BitSet& operator = (const BitSet& set);
// Return true if the bitset are identical.
friend bool operator == (const BitSet& set1, const BitSet& set2);
// Return true if the bitset are different.
friend bool operator != (const BitSet& set1, const BitSet& set2);
// Logical operators.
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
// Return the first bit at set to true or -1 if none.
Int32 firstOne() const {return nextOne(-1);}
// Return the next bit after index set to true or -1 if none.
Int32 nextOne(Int32 pos) const;
// Return the first bit at set to false or -1 if none.
Int32 firstZero() const {return nextZero(-1);}
// Return the next bit after index set to false or -1 if none.
Int32 nextZero(Int32 pos) const;
// Iterator to conform with the set API.
typedef Int32 iterator;
// Return true if the walk is ordered.
static bool isOrdered() {return true;}
// Return the iterator for the first element of this set.
iterator begin() const {return firstOne();}
// Return the next iterator.
iterator advance(iterator pos) const {return nextOne(pos);}
// Return true if the iterator is at the end of the set.
bool done(iterator pos) const {return pos == -1;}
// Return the element corresponding to the given iterator.
Uint32 get(iterator pos) const {return pos;}
#ifdef DEBUG_LOG
// Print the set.
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
// Union with the given bitset.
//
inline void BitSet::or(const BitSet& set)
{
checkUniverseCompatibility(set);
Word* src = set.word;
Word* dst = word;
Word* limit = &src[getSizeInWords(universeSize)];
while (src < limit)
*dst++ |= *src++;
}
// Intersection with the given bitset.
//
inline void BitSet::and(const BitSet& set)
{
checkUniverseCompatibility(set);
Word* src = set.word;
Word* dst = word;
Word* limit = &src[getSizeInWords(universeSize)];
while (src < limit)
*dst++ &= *src++;
}
// Difference with the given bitset.
//
inline void BitSet::difference(const BitSet& set)
{
checkUniverseCompatibility(set);
Word* src = set.word;
Word* dst = word;
Word* limit = &src[getSizeInWords(universeSize)];
while (src < limit)
*dst++ &= ~*src++;
}
// Copy the given set into this set.
//
inline BitSet& BitSet::operator = (const BitSet& set)
{
checkUniverseCompatibility(set);
if (this != &set)
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
return *this;
}
// Return true if the given set is identical to this set.
inline bool operator == (const BitSet& set1, const BitSet& set2)
{
set1.checkUniverseCompatibility(set2);
if (&set1 == &set2)
return true;
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
}
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
#endif // _BITSET_H

View File

@@ -0,0 +1,159 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _COALESCING_H_
#define _COALESCING_H_
#include "Fundamentals.h"
#include "Pool.h"
#include "RegisterPressure.h"
#include "InterferenceGraph.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "SparseSet.h"
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
#if 1
// Performing an ultra conservative coalescing meens that when we look at
// candidates (source,destination) for coalescing we need to make sure
// that the combined interference of the source and destination register
// will not exceed the total number of register available for the register
// class.
#define ULTRA_CONSERVATIVE_COALESCING
#else
// If we are not doing an ultra conservative coalescing we have to make sure
// that the total number of neighbor whose degree is greater than the total
// number of register is not greater than the total number of register.
#undef ULTRA_CONSERVATIVE_COALESCING
#endif
template <class RegisterPressure>
struct Coalescing
{
static bool coalesce(RegisterAllocator& registerAllocator);
};
template <class RegisterPressure>
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
{
Pool& pool = registerAllocator.pool;
// Initialize the lookup table
//
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* newRange = new RegisterName[2 * rangeCount];
RegisterName* coalescedRange = &newRange[rangeCount];
RegisterName* name2range = registerAllocator.name2range;
init(coalescedRange, rangeCount);
SparseSet interferences(pool, rangeCount);
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
bool removedInstructions = false;
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.lndList;
Uint32 nNodes = controlGraph.nNodes;
// Walk the nodes in the loop nesting depth list.
for (Int32 n = nNodes - 1; n >= 0; n--) {
InstructionList& instructions = nodes[n]->getInstructions();
InstructionList::iterator it = instructions.begin();
while (!instructions.done(it)) {
Instruction& instruction = instructions.get(it);
it = instructions.advance(it);
if ((instruction.getFlags() & ifCopy) != 0) {
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
if (source == destination) {
instruction.remove();
} else if (!iGraph.interfere(source, destination)) {
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
#ifdef ULTRA_CONSERVATIVE_COALESCING
interferences.clear();
InterferenceVector* vector;
for (vector = sourceVector; vector != NULL; vector = vector->next) {
RegisterName* neighbors = vector->neighbors;
for (Uint32 i = 0; i < vector->count; i++)
interferences.set(findRoot(neighbors[i], coalescedRange));
}
for (vector = destinationVector; vector != NULL; vector = vector->next) {
RegisterName* neighbors = vector->neighbors;
for (Uint32 i = 0; i < vector->count; i++)
interferences.set(findRoot(neighbors[i], coalescedRange));
}
Uint32 count = interferences.getSize();
#else // ULTRA_CONSERVATIVE_COALESCING
trespass("not implemented");
Uint32 count = 0;
#endif // ULTRA_CONSERVATIVE_COALESCING
if (count < 6 /* FIX: should get the number from the class */) {
// Update the interferences vector.
if (sourceVector == NULL) {
iGraph.setInterferenceVector(source, destinationVector);
sourceVector = destinationVector;
} else if (destinationVector == NULL)
iGraph.setInterferenceVector(destination, sourceVector);
else {
InterferenceVector* last = NULL;
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
last = v;
assert(last);
last->next = destinationVector;
iGraph.setInterferenceVector(destination, sourceVector);
}
// Update the interference matrix.
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
RegisterName* neighbors = v->neighbors;
for (Uint32 i = 0; i < v->count; i++) {
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
iGraph.setInterference(neighbor, source);
iGraph.setInterference(neighbor, destination);
}
}
instruction.remove();
coalescedRange[source] = destination;
removedInstructions = true;
}
}
}
}
}
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
delete newRange;
return removedInstructions;
}
#endif // _COALESCING_H_

View File

@@ -0,0 +1,283 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NEW_LAURENTM_CODE
#include "Coloring.h"
#include "VirtualRegister.h"
#include "FastBitSet.h"
#include "FastBitMatrix.h"
#include "CpuInfo.h"
bool Coloring::
assignRegisters(FastBitMatrix& interferenceMatrix)
{
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
}
PRInt32 Coloring::
getLowestSpillCostRegister(FastBitSet& bitset)
{
PRInt32 lowest = bitset.firstOne();
if (lowest != -1)
{
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
{
cost = vReg.spillInfo.spillCost;
lowest = r;
}
}
}
return lowest;
}
PRUint32* Coloring::
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
{
// first we construct the sets low and high. low contains all nodes of degree
// inferior to the number of register available on the processor. All the
// nodes with an high degree and a finite spill cost are placed in high.
// Nodes of high degree and infinite spill cost are not included in either sets.
PRUint32 nRegisters = vRegManager.count();
FastBitSet low(pool, nRegisters);
FastBitSet high(pool, nRegisters);
FastBitSet stack(pool, nRegisters);
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
if (vReg.getClass() == vrcStackSlot)
{
stack.set(i);
vReg.colorRegister(nRegisters);
}
else
{
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
low.set(i);
else // if (!vReg.spillInfo.infiniteSpillCost)
high.set(i);
// Set coloring info.
vReg.spillInfo.willSpill = false;
switch(vReg.getClass())
{
case vrcInteger:
vReg.colorRegister(LAST_GREGISTER + 1);
break;
case vrcFloatingPoint:
case vrcFixedPoint:
vReg.colorRegister(LAST_FPREGISTER + 1);
break;
default:
PR_ASSERT(false); // Cannot happen.
}
}
}
// push the stack registers
PRInt32 j;
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
*stackPtr++ = j;
// simplify
while (true)
{
PRInt32 r;
while ((r = getLowestSpillCostRegister(low)) != -1)
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
/* update low and high */
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
{
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
// if the new interference degree of one of his neighbor becomes
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
PRUint32 maxInterference = 0;
switch (neighbor.getClass())
{
case vrcInteger:
maxInterference = NUMBER_OF_GREGISTERS;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
maxInterference = NUMBER_OF_FPREGISTERS;
break;
default:
PR_ASSERT(false);
}
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
{
high.clear(j);
low.set(j);
}
vReg.colorInfo.interferenceDegree--;
interferenceMatrix.clear(r, j);
interferenceMatrix.clear(j, r);
}
low.clear(r);
// Push this register.
*stackPtr++ = r;
}
if ((r = getLowestSpillCostRegister(high)) != -1)
{
high.clear(r);
low.set(r);
}
else
break;
}
return stackPtr;
}
bool Coloring::
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
{
PRUint32 nRegisters = vRegManager.count();
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
FastBitSet usedStack(nRegisters + 1);
bool success = true;
Int32 lastUsedSSR = -1;
// select
while (stackPtr != stackBase)
{
// Pop one register.
PRUint32 r = *--stackPtr;
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
if (vReg.getClass() == vrcStackSlot)
// Stack slots coloring.
{
usedStack.clear();
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
Int32 color = usedStack.firstZero();
vReg.colorRegister(color);
if (color > lastUsedSSR)
lastUsedSSR = color;
}
else
// Integer & Floating point register coloring.
{
usedRegisters.clear();
preColoredRegisters.clear();
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
{
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
usedRegisters.set(nvReg.getColor());
if (nvReg.isPreColored())
preColoredRegisters.set(nvReg.getPreColor());
}
if (vReg.hasSpecialInterference)
usedRegisters |= vReg.specialInterference;
PRInt8 c = -1;
PRInt8 maxColor = 0;
PRInt8 firstColor = 0;
switch (vReg.getClass())
{
case vrcInteger:
firstColor = FIRST_GREGISTER;
maxColor = LAST_GREGISTER;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
firstColor = FIRST_FPREGISTER;
maxColor = LAST_FPREGISTER;
break;
default:
PR_ASSERT(false);
}
if (vReg.isPreColored())
{
c = vReg.getPreColor();
if (usedRegisters.test(c))
c = -1;
}
else
{
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
c = usedRegisters.nextZero(c)) {}
}
if ((c >= 0) && (c <= maxColor))
{
vReg.colorRegister(c);
}
else
{
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
vReg.spillInfo.willSpill = true;
success = false;
}
}
}
#ifdef DEBUG
if (success)
{
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
switch (vReg.getClass())
{
case vrcInteger:
if (vReg.getColor() > LAST_GREGISTER)
PR_ASSERT(false);
break;
case vrcFloatingPoint:
case vrcFixedPoint:
#if NUMBER_OF_FPREGISTERS != 0
if (vReg.getColor() > LAST_FPREGISTER)
PR_ASSERT(false);
#endif
break;
default:
break;
}
}
}
#endif
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
return success;
}
#endif // NEW_LAURENTM_CODE

View File

@@ -0,0 +1,284 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "VirtualRegister.h"
#include "InterferenceGraph.h"
#include "SparseSet.h"
#include "Spilling.h"
#include "Splits.h"
UT_EXTERN_LOG_MODULE(RegAlloc);
template <class RegisterPressure>
class Coloring
{
private:
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
public:
static bool color(RegisterAllocator& registerAllocator);
static void finalColoring(RegisterAllocator& registerAllocator);
};
template <class RegisterPressure>
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
{
RegisterName* color = registerAllocator.color;
RegisterName* name2range = registerAllocator.name2range;
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
#ifdef DEBUG
RegisterID rid = usePtr->getRegisterID();
setColoredRegister(rid);
usePtr->setRegisterID(rid);
#endif // DEBUG
}
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
#ifdef DEBUG
RegisterID rid = definePtr->getRegisterID();
setColoredRegister(rid);
definePtr->setRegisterID(rid);
#endif // DEBUG
}
}
}
}
template <class RegisterPressure>
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
{
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* color = new RegisterName[rangeCount];
registerAllocator.color = color;
for (Uint32 r = 1; r < rangeCount; r++)
color[r] = RegisterName(6); // FIX;
// Color the preColored registers.
//
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
RegisterName* name2range = registerAllocator.name2range;
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
if (machinePtr->id != invalidID) {
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
}
SpillCost* cost = registerAllocator.spillCost;
Pool& pool = registerAllocator.pool;
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
registerAllocator.willSpill = &spill;
SparseSet neighborColors(pool, 6); // FIX
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
bool coloringFailed = false;
while (coloringStackPtr > coloringStack) {
RegisterName range = *--coloringStackPtr;
if (!cost[range].infinite && cost[range].cost < 0) {
coloringFailed = true;
spill.set(range);
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
} else {
neighborColors.clear();
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
for (Int32 i = vector->count - 1; i >= 0; --i) {
RegisterName neighborColor = color[vector->neighbors[i]];
if (neighborColor < 6) // FIX
neighborColors.set(neighborColor);
}
if (neighborColors.getSize() == 6) { // FIX
coloringFailed = true;
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
spill.set(range);
} else
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
} else {
for (Uint32 i = 0; i < 6; i++) // FIX
if (!neighborColors.test(i)) {
fprintf(stdout, "\twill color %d as %d\n", range, i);
color[range] = RegisterName(i);
break;
}
}
}
}
#ifdef DEBUG_LOG
if (coloringFailed) {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
spill.printPretty(UT_LOG_MODULE(RegAlloc));
} else {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
for (Uint32 i = 1; i < rangeCount; i++)
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
}
#endif
return !coloringFailed;
}
template <class RegisterPressure>
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
{
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
SpillCost* spillCost = registerAllocator.spillCost;
Uint32 rangeCount = registerAllocator.rangeCount;
Uint32* degree = new Uint32[rangeCount];
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
InterferenceVector* vector = iGraph.getInterferenceVector(i);
degree[i] = (vector != NULL) ? vector->count : 0;
}
Pool& pool = registerAllocator.pool;
SparseSet low(pool, rangeCount);
SparseSet high(pool, rangeCount);
SparseSet highInfinite(pool, rangeCount);
SparseSet preColored(pool, rangeCount);
// Get the precolored registers.
//
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
RegisterName* name2range = registerAllocator.name2range;
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
if (machinePtr->id != invalidID)
preColored.set(name2range[getName(machinePtr->id)]);
// Insert the live ranges in the sets.
//
for (Uint32 range = 1; range < rangeCount; range++)
if (!preColored.test(range))
if (degree[range] < 6) // FIX
low.set(range);
else if (!spillCost[range].infinite)
high.set(range);
else
highInfinite.set(range);
#ifdef DEBUG_LOG
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
low.printPretty(UT_LOG_MODULE(RegAlloc));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
high.printPretty(UT_LOG_MODULE(RegAlloc));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
#endif // DEBUG_LOG
RegisterName* coloringStackPtr = coloringStack;
while (low.getSize() != 0 || high.getSize() != 0) {
while (low.getSize() != 0) {
RegisterName range = RegisterName(low.getOne());
low.clear(range);
*coloringStackPtr++ = range;
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
for (Int32 i = (vector->count - 1); i >= 0; --i) {
RegisterName neighbor = vector->neighbors[i];
degree[neighbor]--;
if (degree[neighbor] < 6) // FIX
if (high.test(neighbor)) {
high.clear(neighbor);
low.set(neighbor);
} else if (highInfinite.test(neighbor)) {
highInfinite.clear(neighbor);
low.set(neighbor);
}
}
}
if (high.getSize() != 0) {
RegisterName best = RegisterName(high.getOne());
double bestCost = spillCost[best].cost;
double bestDegree = degree[best];
// Choose the next best candidate.
//
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
RegisterName range = RegisterName(high.get(i));
double thisCost = spillCost[range].cost;
double thisDegree = degree[range];
if (thisCost * bestDegree < bestCost * thisDegree) {
best = range;
bestCost = thisCost;
bestDegree = thisDegree;
}
}
high.clear(best);
low.set(best);
}
}
assert(highInfinite.getSize() == 0);
delete degree;
#ifdef DEBUG_LOG
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
#endif // DEBUG_LOG
return coloringStackPtr;
}
template <class RegisterPressure>
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
{
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
}

View File

@@ -0,0 +1,212 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include <string.h>
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "DominatorGraph.h"
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
{
Uint32 nNodes = controlGraph.nNodes;
GtoV = new Uint32[nNodes + 1];
VtoG = new Uint32[nNodes + 1];
Uint32 v = 1;
for (Uint32 n = 0; n < nNodes; n++) {
VtoG[v] = n;
GtoV[n] = v++;
}
// Initialize all the 1-based arrays.
//
parent = new Uint32[v];
semi = new Uint32[v];
vertex = new Uint32[v];
label = new Uint32[v];
size = new Uint32[v];
ancestor = new Uint32[v];
child = new Uint32[v];
dom = new Uint32[v];
bucket = new DGLinkedList*[v];
memset(semi, '\0', v * sizeof(Uint32));
memset(bucket, '\0', v * sizeof(DGLinkedList*));
vCount = v;
build();
delete parent;
delete semi;
delete vertex;
delete label;
delete size;
delete ancestor;
delete child;
delete dom;
delete bucket;
}
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
{
semi[vx] = ++n;
vertex[n] = label[vx] = vx;
ancestor[vx] = child[vx] = 0;
size[vx] = 1;
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
ControlEdge* successorEnd = node.getSuccessorsEnd();
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
if (semi[w] == 0) {
parent[w] = vx;
n = DFS(w, n);
}
}
return n;
}
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
{
Uint32 s = w;
while (semi[label[w]] < semi[label[child[s]]]) {
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
ancestor[child[s]] = s;
child[s] = child[child[s]];
} else {
size[child[s]] = size[s];
s = ancestor[s] = child[s];
}
}
label[s] = label[w];
size[vx] += size[w];
if(size[vx] < (size[w] << 1)) {
Uint32 t = s;
s = child[vx];
child[vx] = t;
}
while( s != 0 ) {
ancestor[s] = vx;
s = child[s];
}
}
void DominatorGraph::COMPRESS(Uint32 vx)
{
if(ancestor[ancestor[vx]] != 0) {
COMPRESS(ancestor[vx]);
if(semi[label[ancestor[vx]]] < semi[label[vx]])
label[vx] = label[ancestor[vx]];
ancestor[vx] = ancestor[ancestor[vx]];
}
}
Uint32 DominatorGraph::EVAL(Uint32 vx)
{
if(ancestor[vx] == 0)
return label[vx];
COMPRESS(vx);
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
}
void DominatorGraph::build()
{
Uint32 n = DFS(GtoV[0], 0);
size[0] = label[0] = semi[0];
for (Uint32 i = n; i >= 2; i--) {
Uint32 w = vertex[i];
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
Uint32 u = EVAL(vx);
if(semi[u] < semi[w])
semi[w] = semi[u];
}
DGLinkedList* elem = new DGLinkedList();
elem->next = bucket[vertex[semi[w]]];
elem->index = w;
bucket[vertex[semi[w]]] = elem;
LINK(parent[w], w);
elem = bucket[parent[w]];
while(elem != NULL) {
Uint32 vx = elem->index;
Uint32 u = EVAL(vx);
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
elem = elem->next;
}
}
memset(size, '\0', n * sizeof(Uint32));
Pool& pool = controlGraph.pool;
nodes = new(pool) DGNode[n];
for(Uint32 j = 2; j <= n; j++) {
Uint32 w = vertex[j];
Uint32 d = dom[w];
if(d != vertex[semi[w]]) {
d = dom[d];
dom[w] = d;
}
size[d]++;
}
dom[GtoV[0]] = 0;
for (Uint32 k = 1; k <= n; k++) {
DGNode& node = nodes[VtoG[k]];
Uint32 count = size[k];
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
}
for (Uint32 l = 2; l <= n; l++)
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
}
#ifdef DEBUG_LOG
void DominatorGraph::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 i = 0; i < nNodes; i++) {
DGNode& node = nodes[i];
if (node.successorsBegin != node.successorsEnd) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,80 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _DOMINATOR_GRAPH_H_
#define _DOMINATOR_GRAPH_H_
#include "LogModule.h"
class ControlGraph;
struct DGNode
{
Uint32* successorsBegin;
Uint32* successorsEnd;
};
struct DGLinkedList
{
DGLinkedList* next;
Uint32 index;
};
class DominatorGraph
{
private:
ControlGraph& controlGraph;
Uint32 vCount;
Uint32* VtoG;
Uint32* GtoV;
Uint32* parent;
Uint32* semi;
Uint32* vertex;
Uint32* label;
Uint32* size;
Uint32* ancestor;
Uint32* child;
Uint32* dom;
DGLinkedList** bucket;
DGNode* nodes;
private:
void build();
Uint32 DFS(Uint32 vx, Uint32 n);
void LINK(Uint32 vx, Uint32 w);
void COMPRESS(Uint32 vx);
Uint32 EVAL(Uint32 vx);
public:
DominatorGraph(ControlGraph& controlGraph);
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
#ifdef DEBUG_LOG
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
#endif // _DOMINATOR_GRAPH_H_

View File

@@ -0,0 +1,20 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "HashSet.h"

View File

@@ -0,0 +1,97 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _HASH_SET_H_
#define _HASH_SET_H_
#include "Fundamentals.h"
#include "Pool.h"
#include <string.h>
struct HashSetElement
{
Uint32 index;
HashSetElement* next;
};
class HashSet
{
private:
static const hashSize = 64;
// Return the hash code for the given element index.
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
private:
Pool& allocationPool;
HashSetElement** bucket;
HashSetElement* free;
private:
// No copy constructor.
HashSet(const HashSet&);
// No copy operator.
void operator = (const HashSet&);
public:
// Create a new HashSet.
inline HashSet(Pool& pool, Uint32 universeSize);
// Clear the hashset.
void clear();
// Clear the element for the given index.
void clear(Uint32 index);
// Set the element for the given index.
void set(Uint32 index);
// Return true if the element at index is a member.
bool test(Uint32 index) const;
// Union with the given hashset.
inline void or(const HashSet& set);
// Intersection with the given hashset.
inline void and(const HashSet& set);
// Difference with the given hashset.
inline void difference(const HashSet& set);
// Logical operators.
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
// Iterator to conform with the set API.
typedef HashSetElement* iterator;
// Return the iterator for the first element of this set.
iterator begin() const;
// Return the next iterator.
iterator advance(iterator pos) const;
// Return true if the iterator is at the end of the set.
bool done(iterator pos) const {return pos == NULL;}
};
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
: allocationPool(pool), free(NULL)
{
bucket = new(pool) HashSetElement*[hashSize];
memset(bucket, '\0', sizeof(HashSetElement*));
}
#endif // _HASH_SET_H_

View File

@@ -0,0 +1,213 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _INDEXED_POOL_H_
#define _INDEXED_POOL_H_
#include "Fundamentals.h"
#include <string.h>
#include <stdlib.h>
//------------------------------------------------------------------------------
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
// IndexedObject.
//
// When the indexed pool is ask to allocate and initialize a new object (using
// the operator new(anIndexedPool) it will zero the memory used to store the
// object and initialize the field 'index' of this object to its position in
// the pool.
//
// An object allocated by the indexed pool can be freed by calling the method
// IndexedPool::release(IndexedElement& objectIndex).
//
// example:
//
// IndexedPool<IndexedElement> elementPool;
//
// IndexedElement& element1 = *new(elementPool) IndexedElement();
// IndexedElement& element2 = *new(elementPool) IndexedElement();
//
// indexedPool.release(element1);
// IndexedElement& element3 = *new(elementPool) IndexedElement();
//
// At this point element1 is no longer a valid object, element2 is at
// index 2 and element3 is at index 1.
//
//------------------------------------------------------------------------------
// IndexedObject -
//
template<class Object>
struct IndexedObject
{
Uint32 index; // Index in the pool.
Object* next; // Used to link IndexedObject together.
Uint32 getIndex() {return index;}
};
//------------------------------------------------------------------------------
// IndexedPool<IndexedObject> -
//
template <class IndexedObject>
class IndexedPool
{
private:
static const blockSize = 4; // Size of one block.
Uint32 nBlocks; // Number of blocks in the pool.
IndexedObject** block; // Array of block pointers.
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
Uint32 nextIndex; // Index of the next free object in the last block.
private:
void allocateAnotherBlock();
IndexedObject& newObject();
public:
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
~IndexedPool();
IndexedObject& get(Uint32 index) const;
void release(IndexedObject& object);
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
// Return the universe size.
Uint32 getSize() {return nextIndex;}
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
};
// Free all the memory allocated for this object.
//
template <class IndexedObject>
IndexedPool<IndexedObject>::~IndexedPool()
{
for (Uint32 n = 0; n < nBlocks; n++)
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
}
// Release the given. This object will be iserted in the chained
// list of free IndexedObjects. To minimize the fragmentation the chained list
// is ordered by ascending indexes.
//
template <class IndexedObject>
void IndexedPool<IndexedObject>::release(IndexedObject& object)
{
Uint32 index = object.index;
IndexedObject* list = freeObjects;
assert(&object == &get(index)); // Make sure that object is owned by this pool.
if (list == NULL) { // The list is empty.
freeObjects = &object;
object.next = NULL;
} else { // The list contains at least 1 element.
if (index < list->index) { // insert as first element.
freeObjects = &object;
object.next = list;
} else { // Find this object's place.
while ((list->next) != NULL && (list->next->index < index))
list = list->next;
object.next = list->next;
list->next = &object;
}
}
#ifdef DEBUG
// Sanity check to be sure that the list is correctly ordered.
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
if (obj->next != NULL)
assert(obj->index < obj->next->index);
#endif
}
// Create a new block of IndexedObjects. We will allocate the memory to
// store IndexedPool::blockSize IndexedObject and the new Array of block
// pointers.
// The newly created IndexedObjects will not be initialized.
//
template <class IndexedObject>
void IndexedPool<IndexedObject>::allocateAnotherBlock()
{
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
memcpy(memory, block, nBlocks * sizeof(Uint32));
block = (IndexedObject **) memory;
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
block[nBlocks] = &objects[-(nBlocks * blockSize)];
nBlocks++;
}
// Return the IndexedObject at the position 'index' in the pool.
//
template <class IndexedObject>
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
{
Uint32 blockIndex = index / blockSize;
assert(blockIndex < nBlocks);
return block[blockIndex][index];
}
// Return the reference of an unused object in the pool.
//
template <class IndexedObject>
IndexedObject& IndexedPool<IndexedObject>::newObject()
{
if (freeObjects != NULL) {
IndexedObject& newObject = *freeObjects;
freeObjects = newObject.next;
return newObject;
}
Uint32 nextIndex = this->nextIndex++;
Uint32 blockIndex = nextIndex / blockSize;
while (blockIndex >= nBlocks)
allocateAnotherBlock();
IndexedObject& newObject = block[blockIndex][nextIndex];
newObject.index = nextIndex;
return newObject;
}
// Return the address of the next unsused object in the given
// indexed pool. The field index of the newly allocated object
// will be initialized to the corresponding index of this object
// in the pool.
//
template <class IndexedObject>
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
{
assert(size == sizeof(IndexedObject));
return (void *) &pool.newObject();
}
#endif // _INDEXED_POOL_H_

View File

@@ -0,0 +1,258 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _INTERFERENCE_GRAPH_H_
#define _INTERFERENCE_GRAPH_H_
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "Primitives.h"
#include "Instruction.h"
#include "VirtualRegister.h"
#include "RegisterPressure.h"
#include "SparseSet.h"
#include <string.h>
struct InterferenceVector
{
Uint32 count;
InterferenceVector* next;
RegisterName* neighbors;
InterferenceVector() : count(0), next(NULL) {}
};
class RegisterAllocator;
template <class RegisterPressure>
class InterferenceGraph
{
private:
RegisterAllocator& registerAllocator;
RegisterPressure::Set* interferences;
InterferenceVector** vector;
Uint32* offset;
Uint32 rangeCount;
private:
// No copy constructor.
InterferenceGraph(const InterferenceGraph&);
// No copy operator.
void operator = (const InterferenceGraph&);
// Check if reg is a member of the universe.
void checkMember(RegisterName name) {assert(name < rangeCount);}
// Return the edge index for the interference between name1 and name2.
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
public:
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
// Calculate the interferences.
void build();
// Return true if reg1 and reg2 interfere.
bool interfere(RegisterName name1, RegisterName name2);
// Return the interference vector for the given register or NULL if there is none.
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
// Set the interference between name1 and name2.
void setInterference(RegisterName name1, RegisterName name2);
// Set the interference vector for the given register.
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
#ifdef DEBUG_LOG
// Print the interferences.
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
template <class RegisterPressure>
void InterferenceGraph<RegisterPressure>::build()
{
Pool& pool = registerAllocator.pool;
Uint32 rangeCount = registerAllocator.rangeCount;
this->rangeCount = rangeCount;
// Initialize the structures.
//
offset = new(pool) Uint32[rangeCount + 1];
vector = new(pool) InterferenceVector*[rangeCount];
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
Uint32 o = 0;
offset[0] = 0;
for (Uint32 i = 1; i <= rangeCount; ++i) {
offset[i] = o;
o += i;
}
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
registerAllocator.liveness = liveness;
SparseSet currentLive(pool, rangeCount);
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
currentLive = liveness.liveOut[n];
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
if ((instruction.getFlags() & ifCopy) != 0) {
assert(useBegin != useEnd && useBegin[0].isRegister());
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
}
// Create the interferences.
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName define = name2range[definePtr->getRegisterName()];
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
RegisterName live = RegisterName(currentLive.get(e));
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
if (vector[define] == NULL)
vector[define] = new(pool) InterferenceVector();
vector[define]->count++;
if (vector[live] == NULL)
vector[live] = new(pool) InterferenceVector();
vector[live]->count++;
setInterference(live, define);
}
}
}
// Now update the liveness.
//
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentLive.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
currentLive.set(name2range[usePtr->getRegisterName()]);
}
}
// Allocate the memory to store the interferences.
//
for (Uint32 e = 0; e < rangeCount; e++)
if (vector[e] != NULL) {
InterferenceVector& v = *vector[e];
v.neighbors = new(pool) RegisterName[v.count];
v.count = 0;
}
// Initialize the edges.
//
if (RegisterPressure::Set::isOrdered()) {
RegisterName name1 = RegisterName(0);
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
Uint32 interferenceIndex = interferences->get(i);
while(interferenceIndex >= offset[name1 + 1])
name1 = RegisterName(name1 + 1);
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
assert(interfere(name1, name2));
InterferenceVector& vector1 = *vector[name1];
vector1.neighbors[vector1.count++] = name2;
InterferenceVector& vector2 = *vector[name2];
vector2.neighbors[vector2.count++] = name1;
}
} else {
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
}
}
template <class RegisterPressure>
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
{
checkMember(name1); checkMember(name2);
assert(name1 != name2); // This is not possible.
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
}
template <class RegisterPressure>
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
{
interferences->set(getEdgeIndex(name1, name2));
}
template <class RegisterPressure>
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
{
return interferences->test(getEdgeIndex(name1, name2));
}
#ifdef DEBUG_LOG
template <class RegisterPressure>
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
for (Uint32 i = 1; i < rangeCount; i++) {
if (vector[i] != NULL) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
for (Uint32 j = 0; j < v->count; j++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
if (v->next != NULL || j != (v->count - 1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
}
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
}
}
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
#endif // DEBUG_LOG
#endif // _INTERFERENCE_GRAPH_H_

View File

@@ -0,0 +1,87 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _LIVE_RANGE_H_
#define _LIVE_RANGE_H_
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Primitives.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
template <class RegisterPressure>
struct LiveRange
{
static void build(RegisterAllocator& registerAllocator);
};
template <class RegisterPressure>
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
{
// Intialize the lookup table.
//
Uint32 nameCount = registerAllocator.nameCount;
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
RegisterName* rangeName = &nameTable[nameCount];
init(rangeName, nameCount);
// Walk the graph.
//
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
SparseSet destination(registerAllocator.pool, nameCount);
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
destination.clear();
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
Instruction& phiNode = phiNodes.get(i);
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
}
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
RegisterName destinationRoot = findRoot(destinationName, rangeName);
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
assert(usePtr->isRegister());
RegisterName sourceName = usePtr->getRegisterName();
RegisterName sourceRoot = findRoot(sourceName, rangeName);
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
rangeName[sourceRoot] = destinationRoot;
}
}
}
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
}
#endif // _LIVE_RANGE_H_

View File

@@ -0,0 +1,163 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _LIVE_RANGE_GRAPH_
#define _LIVE_RANGE_GRAPH_
#include "Fundamentals.h"
#include "Pool.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterTypes.h"
class RegisterAllocator;
template <class RegisterPressure>
class LiveRangeGraph
{
private:
RegisterAllocator& registerAllocator;
RegisterPressure::Set* edges;
Uint32 rangeCount;
public:
//
//
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
//
//
void build();
//
//
void addEdge(RegisterName name1, RegisterName name2);
//
//
bool haveEdge(RegisterName name1, RegisterName name2);
#ifdef DEBUG_LOG
//
//
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
template <class RegisterPressure>
void LiveRangeGraph<RegisterPressure>::build()
{
Pool& pool = registerAllocator.pool;
Uint32 rangeCount = registerAllocator.rangeCount;
this->rangeCount = rangeCount;
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
SparseSet currentLive(pool, rangeCount);
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
currentLive = liveness.liveOut[n];
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
if ((instruction.getFlags() & ifCopy) != 0) {
assert(useBegin != useEnd && useBegin[0].isRegister());
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName define = name2range[definePtr->getRegisterName()];
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
RegisterName live = RegisterName(currentLive.get(l));
if (define != live && registerAllocator.canInterfere(define, live))
addEdge(define, live);
}
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentLive.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
currentLive.set(name2range[usePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName use = name2range[usePtr->getRegisterName()];
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
RegisterName live = RegisterName(currentLive.get(l));
if (use != live && registerAllocator.canInterfere(use, live))
addEdge(use, live);
}
}
}
}
}
template <class RegisterPressure>
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
{
assert(name1 != name2);
edges->set(name1 * rangeCount + name2);
}
template <class RegisterPressure>
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
{
assert(name1 != name2);
return edges->test(name1 * rangeCount + name2);
}
#ifdef DEBUG_LOG
template <class RegisterPressure>
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
{
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
#endif // DEBUG_LOG
#endif // _LIVE_RANGE_GRAPH_

View File

@@ -0,0 +1,21 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "Liveness.h"

View File

@@ -0,0 +1,301 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _LIVENESS_H_
#define _LIVENESS_H_
#include "Fundamentals.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterTypes.h"
// ----------------------------------------------------------------------------
// LivenessInfo -
template <class RegisterPressure>
struct LivenessInfo
{
RegisterPressure::Set* liveIn;
RegisterPressure::Set* liveOut;
DEBUG_LOG_ONLY(Uint32 size);
#ifdef DEBUG_LOG
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
// ----------------------------------------------------------------------------
// Liveness
//
// The liveness is defined by the following data-flow equations:
//
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
// LiveOut(n) = U LiveIn(s) (s a successor of n).
//
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
// is the set of defined registers in the block n, LiveIn(n) is the set of
// live registers at the begining of the block n and LiveOut(n) is the set
// of live registers at the end of the block n.
//
//
// We will compute the liveness analysis in two stages:
//
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
// for each block n.
// 2- Perform a backward data-flow analysis to propagate the liveness information
// through the entire control-flow graph.
//
template <class RegisterPressure>
struct Liveness
{
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
};
template <class RegisterPressure>
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
// Allocate the temporary sets.
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
// Allocate the globals sets.
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
//
for (Uint32 n = 0; n < (nNodes - 1); n++) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLocalLive = liveIn[n];
RegisterPressure::Set& currentKilled = killed[n];
// Find the instructions contributions to the sets LocalLive and Killed.
//
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
Uint32 index = name2range[usePtr->getRegisterName()];
if (!currentKilled.test(index))
currentLocalLive.set(index);
}
// If a Virtualregister is 'defined' then we add it to the set Killed.
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentKilled.set(name2range[definePtr->getRegisterName()]);
}
}
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
// control-flow graph.
//
RegisterPressure::Set temp(pool, rangeCount);
bool changed;
do {
changed = false;
// For all nodes is this graph except the endNode.
for (Int32 n = (nNodes - 2); n >= 0; n--) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLiveIn = liveIn[n];
RegisterPressure::Set& currentLiveOut = liveOut[n];
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
// temp will be the new LiveOut(n).
Uint32 nSuccessors = node.nSuccessors();
if (nSuccessors != 0) {
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
for (Uint32 s = 1; s < nSuccessors; s++)
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
} else
temp.clear();
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
// new LiveIn(n).
if (currentLiveOut != temp) {
currentLiveOut = temp;
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
temp |= currentLiveIn;
if (currentLiveIn != temp) {
currentLiveIn = temp;
changed = true;
}
}
}
} while(changed);
LivenessInfo<RegisterPressure> liveness;
liveness.liveIn = liveIn;
liveness.liveOut = liveOut;
DEBUG_LOG_ONLY(liveness.size = nNodes);
return liveness;
}
template <class RegisterPressure>
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
// Allocate the temporary sets.
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
RegisterPressure::Set* usedByPhiNodes = NULL;
// Allocate the globals sets.
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
//
for (Uint32 n = 0; n < (nNodes - 1); n++) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLocalLive = liveIn[n];
RegisterPressure::Set& currentKilled = killed[n];
InstructionList& phiNodes = node.getPhiNodeInstructions();
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
currentKilled.set(define.getRegisterName());
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
const ControlEdgeList& predecessors = node.getPredecessors();
ControlEdgeList::iterator p = predecessors.begin();
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
if (usePtr->isRegister())
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
}
// Find the instructions contributions to the sets LocalLive and Killed.
//
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
Uint32 index = usePtr->getRegisterName();
if (!currentKilled.test(index))
currentLocalLive.set(index);
}
// If a Virtualregister is 'defined' then we add it to the set Killed.
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentKilled.set(definePtr->getRegisterName());
}
}
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
// control-flow graph.
//
RegisterPressure::Set temp(pool, nameCount);
bool changed;
do {
changed = false;
// For all nodes is this graph except the endNode.
for (Int32 n = (nNodes - 2); n >= 0; n--) {
ControlNode& node = *nodes[n];
RegisterPressure::Set& currentLiveIn = liveIn[n];
RegisterPressure::Set& currentLiveOut = liveOut[n];
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
// temp will be the new LiveOut(n).
Uint32 nSuccessors = node.nSuccessors();
if (nSuccessors != 0) {
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
for (Uint32 s = 1; s < nSuccessors; s++)
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
} else
temp.clear();
// Insert the phiNodes contribution.
if (usedByPhiNodes != NULL)
temp |= usedByPhiNodes[n];
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
// new LiveIn(n).
if (currentLiveOut != temp) {
currentLiveOut = temp;
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
temp |= currentLiveIn;
if (currentLiveIn != temp) {
currentLiveIn = temp;
changed = true;
}
}
}
} while(changed);
LivenessInfo<RegisterPressure> liveness;
liveness.liveIn = liveIn;
liveness.liveOut = liveOut;
DEBUG_LOG_ONLY(liveness.size = nNodes);
return liveness;
}
#ifdef DEBUG_LOG
template <class RegisterPressure>
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
{
for (Uint32 n = 0; n < size; n++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
liveIn[n].printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
liveOut[n].printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
#endif // DEBUG_LOG
#endif // _LIVENESS_H_

View File

@@ -0,0 +1,40 @@
#! gmake
DEPTH = ../..
MODULE_NAME = RegisterAllocator
include $(DEPTH)/config/config.mk
INCLUDES += \
-I$(DEPTH)/Utilities/General \
-I$(DEPTH)/Utilities/zlib \
-I$(DEPTH)/Runtime/ClassReader \
-I$(DEPTH)/Runtime/NativeMethods \
-I$(DEPTH)/Runtime/System \
-I$(DEPTH)/Runtime/ClassInfo \
-I$(DEPTH)/Runtime/FileReader \
-I$(DEPTH)/Compiler/PrimitiveGraph \
-I$(DEPTH)/Compiler/FrontEnd \
-I$(DEPTH)/Compiler/Optimizer \
-I$(DEPTH)/Compiler/CodeGenerator \
-I$(DEPTH)/Compiler/CodeGenerator/md \
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
-I$(DEPTH)/Compiler/RegisterAllocator \
-I$(DEPTH)/Driver/StandAloneJava \
-I$(DEPTH)/Debugger \
$(NULL)
CXXSRCS = \
RegisterAllocator.cpp \
RegisterAllocatorTools.cpp \
DominatorGraph.cpp \
VirtualRegister.cpp \
BitSet.cpp \
SparseSet.cpp \
$(NULL)
include $(DEPTH)/config/rules.mk
libs:: $(MODULE)

View File

@@ -0,0 +1,392 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _PHI_NODE_REMOVER_H_
#define _PHI_NODE_REMOVER_H_
#include "Fundamentals.h"
#include "Pool.h"
#include "ControlGraph.h"
#include "DominatorGraph.h"
#include "VirtualRegister.h"
#include "RegisterPressure.h"
#include "Liveness.h"
#include "Instruction.h"
#include "InstructionEmitter.h"
#include "SparseSet.h"
#include <string.h>
//------------------------------------------------------------------------------
// RegisterNameNode -
struct RegisterNameNode
{
RegisterNameNode* next;
RegisterName newName;
Uint32 nextPushed;
};
//------------------------------------------------------------------------------
// CopyData -
struct CopyData
{
RegisterName source;
RegisterClassKind classKind;
Uint32 useCount;
bool isLiveOut;
RegisterName sourceNameToUse;
RegisterName temporaryName;
RegisterNameNode* newName;
};
//------------------------------------------------------------------------------
// PhiNodeRemover<RegisterPressure> -
template <class RegisterPressure>
struct PhiNodeRemover
{
// Replace the phi nodes by copy instructions.
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
};
// Split some of the critical edges and return true if there are still some
// in the graph after that.
//
static bool splitCriticalEdges(ControlGraph& /*cg*/)
{
// FIX: not implemented.
return true;
}
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
{
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
if (pushed.test(oldName))
(*stack)->newName = newName;
else {
newNode.newName = newName;
newNode.nextPushed = *nodeListPointer;
*nodeListPointer = oldName;
newNode.next = *stack;
*stack = &newNode;
pushed.set(oldName);
}
}
template <class RegisterPressure>
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
// Initialize the local variables.
//
// When we insert the copies we will also need to create new VirtualRegisters for
// the insertion of temporaries. The maximum number of temporary register will not
// exceed the number of phiNodes in the primitive graph.
Uint32 nameCount = vrManager.getSize();
Uint32 maxNameCount = nameCount;
for (Uint32 n = 0; n < nNodes; n++)
maxNameCount += nodes[n]->getPhiNodes().length();
// If the CFG contains some critical edges (backward edge which source has more than one
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
// information to be able to insert temporary copies.
RegisterPressure::Set* liveOut = NULL;
if (splitCriticalEdges(controlGraph))
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
DominatorGraph dGraph(controlGraph);
SparseSet pushed(pool, maxNameCount);
SparseSet destinationList(pool, maxNameCount);
SparseSet workList(pool, maxNameCount);
CopyData* copyStats = new(pool) CopyData[maxNameCount];
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
struct NodeStack {
Uint32* next;
Uint32* limit;
Uint32 pushedList;
};
// Allocate the node stack and initialize the node stack pointer.
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
NodeStack* nodeStackPtr = nodeStack;
// We start by the begin node.
Uint32 startNode = 0;
Uint32* next = &startNode;
Uint32* limit = &startNode + 1;
while (true) {
if (next == limit) {
// If there are no more node in the sibling, we have to pop the current
// frame from the stack and update the copyStats of the pushed nodes.
//
if (nodeStackPtr == nodeStack)
// We are at the bottom of the stack and there are no more nodes
// to look at. We are done !
break;
--nodeStackPtr;
// We are done with all the children of this node in the dominator tree.
// We need to update the copy information of all the new names pushed
// during the walk over this node.
Uint32 pushedList = nodeStackPtr->pushedList;
while (pushedList != 0) {
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
pushedList = nextName;
}
// restore the previous frame.
next = nodeStackPtr->next;
limit = nodeStackPtr->limit;
} else {
Uint32 currentNode = *next++;
Uint32 pushedList = 0;
// Initialize the sets.
pushed.clear();
destinationList.clear();
// STEP1:
// Walk the instruction list and to replace all the instruction uses with their new name.
// If the instruction is a phi node and its defined register is alive at the end of this
// block then we push the defined register into the stack.
//
ControlNode& node = *nodes[currentNode];
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
InstructionList& phiNodes = node.getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
assert(usePtr->isRegister());
RegisterName name = usePtr->getRegisterName();
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
usePtr->setRegisterName(copyStats[name].newName->newName);
}
if (currentLiveOut != NULL) {
// This is a phi node and we have to push its defined name if it is live
// at the end of the node. We only need to do this if the CFG has critical edges.
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
if (currentLiveOut->test(name))
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
}
}
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName name = usePtr->getRegisterName();
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
usePtr->setRegisterName(copyStats[name].newName->newName);
}
}
// STEP2:
// Look at this node's successors' phiNodes. We keep track of the number of time
// a VR will be used by another copy instruction and insert each definition into the
// destinationList. This is the only pass over this node's successors as we will
// get all the information we need in the CopyData structures.
//
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
Uint32 useIndex = successorEdgePtr->getIndex();
ControlNode& successor = successorEdgePtr->getTarget();
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
// as soon as we find an instruction which is not a phi node
InstructionList& phiNodes = successor.getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& phiNode = phiNodes.get(p);
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
assert(source.isRegister() && destination.isRegister());
RegisterName sourceName = source.getRegisterName();
RegisterName destinationName = destination.getRegisterName();
// Get the correct name for the source.
if (copyStats[sourceName].newName != NULL)
sourceName = copyStats[sourceName].newName->newName;
// Update the CopyData structures.
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
copyStats[destinationName].source = sourceName;
copyStats[destinationName].classKind = destination.getRegisterClass();
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
copyStats[destinationName].sourceNameToUse = destinationName;
copyStats[sourceName].sourceNameToUse = sourceName;
copyStats[sourceName].useCount++;
destinationList.set(destinationName);
}
}
}
// STEP3:
// Insert into the worklist only the destination registers that will be not used in
// another copy instruction in this block.
//
assert(workList.getSize() == 0);
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
Uint32 dest = destinationList.get(d);
if (copyStats[dest].useCount == 0)
workList.set(dest);
}
// STEP4:
// Insert the copy instructions.
//
Uint32 destinationListSize = destinationList.getSize();
InstructionList::iterator endOfTheNode = instructions.end();
// Find the right place to insert the copy instructions.
if (destinationListSize != 0)
while (instructions.get(endOfTheNode).getFlags() & ifControl)
endOfTheNode = instructions.retreat(endOfTheNode);
while (destinationListSize != 0) {
while(workList.getSize()) {
RegisterName destinationName = RegisterName(workList.getOne());
RegisterName sourceName = copyStats[destinationName].source;
workList.clear(destinationName);
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
// Lost copy problem.
copyStats[destinationName].isLiveOut = false;
RegisterName sourceName = destinationName;
RegisterClassKind classKind = copyStats[sourceName].classKind;
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
assert(destinationName < maxNameCount);
copyStats[destinationName].classKind = classKind;
copyStats[sourceName].useCount = 0;
// We need to insert a copy to a temporary register to keep the
// source register valid at the end of the node defining it.
// This copy will be inserted right after the phi node defining it.
RegisterName from = copyStats[sourceName].sourceNameToUse;
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
RegisterID fromID = buildRegisterID(from, classKind);
RegisterID toID = buildRegisterID(destinationName, classKind);
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
copyStats[sourceName].temporaryName = destinationName;
copyStats[sourceName].sourceNameToUse = destinationName;
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
}
// Insert the copy instruction at the end of the current node.
RegisterName from = copyStats[sourceName].sourceNameToUse;
RegisterClassKind classKind = copyStats[destinationName].classKind;
RegisterID fromID = buildRegisterID(from, classKind);
RegisterID toID = buildRegisterID(destinationName, classKind);
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
instructions.insertAfter(copy, endOfTheNode);
endOfTheNode = instructions.advance(endOfTheNode);
copyStats[sourceName].useCount = 0;
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
copyStats[sourceName].isLiveOut = false;
copyStats[sourceName].sourceNameToUse = destinationName;
if (destinationList.test(sourceName))
workList.set(sourceName);
destinationList.clear(destinationName);
}
destinationListSize = destinationList.getSize();
if (destinationListSize != 0) {
RegisterName sourceName = RegisterName(destinationList.getOne());
RegisterName destinationName;
if (!copyStats[sourceName].temporaryName) {
// Cycle problem.
RegisterClassKind classKind = copyStats[sourceName].classKind;
destinationName = getName(vrManager.newVirtualRegister(classKind));
assert(destinationName < maxNameCount);
copyStats[destinationName].classKind = classKind;
copyStats[sourceName].temporaryName = destinationName;
// Insert the copy instruction at the end of the current node.
RegisterName from = copyStats[sourceName].sourceNameToUse;
RegisterID fromID = buildRegisterID(from, classKind);
RegisterID toID = buildRegisterID(destinationName, classKind);
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
instructions.insertAfter(copy, endOfTheNode);
endOfTheNode = instructions.advance(endOfTheNode);
} else
destinationName = copyStats[sourceName].temporaryName;
copyStats[sourceName].useCount = 0;
copyStats[sourceName].isLiveOut = false;
copyStats[sourceName].sourceNameToUse = destinationName;
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
workList.set(sourceName);
}
}
nodeStackPtr->pushedList = pushedList;
nodeStackPtr->next = next;
nodeStackPtr->limit = limit;
++nodeStackPtr;
next = dGraph.getSuccessorsBegin(currentNode);
limit = dGraph.getSuccessorsEnd(currentNode);
}
}
}
#endif // _PHI_NODE_REMOVER_H_

View File

@@ -0,0 +1,155 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "LogModule.h"
#include "RegisterAllocator.h"
#include "RegisterPressure.h"
#include "RegisterAllocatorTools.h"
#include "PhiNodeRemover.h"
#include "LiveRange.h"
#include "Liveness.h"
#include "InterferenceGraph.h"
#include "LiveRangeGraph.h"
#include "Coalescing.h"
#include "Spilling.h"
#include "Coloring.h"
#include "Splits.h"
class Pool;
class ControlGraph;
class VirtualRegisterManager;
class InstructionEmitter;
UT_DEFINE_LOG_MODULE(RegAlloc);
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
{
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
// some special code for the high word annotation.
//
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
// Perform some tests on the instruction graph.
//
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
// Replace the phi node instructions by their equivalent copy instructions.
//
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
// Do the register allocation.
//
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
registerAllocator.doGraphColoring();
}
void RegisterAllocator::doGraphColoring()
{
// Initialize the liverange map.
//
initLiveRanges();
// Build the live ranges. We do this to compress the number of RegisterNames
// used in the insterference graph.
//
LiveRange<LowRegisterPressure>::build(*this);
// Remove unnecessary copies.
//
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
for (Uint8 loop = 0; loop < 10; loop++) {
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
while(true) {
// Build the interference graph.
//
iGraph.build();
// Coalesce the copy instructions.
//
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
break;
}
// Print the interference graph.
//
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
// Calculate the spill costs.
//
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
// Calculate the split costs.
//
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
// Build the live range graph.
//
lGraph.build();
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
// Color the graph. If it succeeds then we're done with the
// register allocation.
//
if (Coloring<LowRegisterPressure>::color(*this)) {
// Write the final colors in the instruction graph.
//
Coloring<LowRegisterPressure>::finalColoring(*this);
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
return;
}
// We need to spill some registers.
//
Spilling<LowRegisterPressure>::insertSpillCode(*this);
// Insert the split instructions.
//
Splits<LowRegisterPressure>::insertSplitCode(*this);
// Update the live ranges.
//
// FIX
}
#ifdef DEBUG_LOG
RegisterAllocatorTools::updateInstructionGraph(*this);
RegisterAllocatorTools::printInstructions(*this);
#endif
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
abort();
}
void RegisterAllocator::initLiveRanges()
{
Uint32 count = this->nameCount;
RegisterName* name2range = new(pool) RegisterName[nameCount];
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
name2range[r] = r;
this->name2range = name2range;
rangeCount = count;
}

View File

@@ -0,0 +1,88 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_ALLOCATOR_H_
#define _REGISTER_ALLOCATOR_H_
class Pool;
class ControlGraph;
class InstructionEmitter;
struct SpillCost;
struct SplitCost;
#include "Liveness.h"
#include "VirtualRegister.h"
#include "RegisterPressure.h" // This should included by Backend.cpp
#include "InterferenceGraph.h"
#include "LiveRangeGraph.h"
//template <class RegisterPressure>
class RegisterAllocator
{
public:
Pool& pool; //
ControlGraph& controlGraph; //
VirtualRegisterManager& vrManager; //
InstructionEmitter& emitter; //
RegisterName* name2range; //
RegisterName* color; //
SpillCost* spillCost; //
SparseSet* willSpill; //
SplitCost* splitCost; //
NameLinkedList** splitAround; //
InterferenceGraph<LowRegisterPressure> iGraph; //
LiveRangeGraph<LowRegisterPressure> lGraph; //
LivenessInfo<LowRegisterPressure> liveness; //
Uint32 nameCount; //
Uint32 rangeCount; //
bool splitFound; //
private:
//
//
void doGraphColoring();
public:
//
//
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
//
//
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
//
//
void initLiveRanges();
//
//
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
};
//
//
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
#endif // _REGISTER_ALLOCATOR_H_

View File

@@ -0,0 +1,355 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "LogModule.h"
#include "RegisterAllocatorTools.h"
#include "Pool.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Primitives.h"
#include "InstructionEmitter.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "Spilling.h"
#include "Splits.h"
#include "BitSet.h"
UT_EXTERN_LOG_MODULE(RegAlloc);
#ifdef DEBUG
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
{
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
Uint32 nameCount = vrManager.getSize();
BitSet registerSeen(controlGraph.pool, nameCount);
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
registerSeen.set(usePtr->getRegisterName());
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
registerSeen.set(definePtr->getRegisterName());
}
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& instruction = phiNodes.get(p);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
registerSeen.set(usePtr->getRegisterName());
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
registerSeen.set(definePtr->getRegisterName());
}
}
bool renameRegisters = false;
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
renameRegisters = true;
fprintf(stderr,
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
" is never used nor defined by any instruction in the instruction graph\n"
" PLEASE FIX \n",
i);
}
if (renameRegisters) {
Instruction** definingInstruction = new Instruction*[nameCount];
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
RegisterName* newName = new RegisterName[nameCount];
memset(newName, '\0', nameCount * sizeof(RegisterName));
RegisterName nextName = RegisterName(1);
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName name = usePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
usePtr->setRegisterName(newName[name]);
}
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName name = definePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
definePtr->setRegisterName(newName[name]);
}
}
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& instruction = phiNodes.get(p);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName name = usePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
usePtr->setRegisterName(newName[name]);
}
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName name = definePtr->getRegisterName();
if (newName[name] == rnInvalid) {
newName[name] = nextName;
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
nextName = RegisterName(nextName + 1);
}
definePtr->setRegisterName(newName[name]);
}
}
}
vrManager.setSize(nextName);
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
for (Uint32 i = 1; i < nameCount; i++)
if (newName[i] != 0)
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
else
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
delete newName;
delete definingInstruction;
}
}
#endif // DEBUG
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
{
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
Instruction& instruction = instructions.get(i);
i = instructions.advance(i);
if (instruction.getFlags() & ifCopy) {
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
if (source == destination)
instruction.remove();
}
}
}
}
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
{
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
RegisterName* name2range = registerAllocator.name2range;
for (Uint32 n = 0; n < nNodes; n++) {
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
}
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
Instruction& instruction = phiNodes.get(p);
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
}
}
}
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
{
Pool& pool = controlGraph.pool;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
if (!phiNodes.empty()) {
// Set the index of the incoming edges.
Uint32 index = 0;
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
predecessors.get(p).setIndex(index++);
// Insert the phi node instruction in the instruction list.
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
PhiNode& phiNode = phiNodes.get(i);
ValueKind kind = phiNode.getKind();
if (!isStorableKind(kind))
continue;
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
Uint32 nInputs = phiNode.nInputs();
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
node.addPhiNodeInstruction(phiNodeInstruction);
if (isDoublewordKind(kind)) {
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
node.addPhiNodeInstruction(phiNodeInstruction);
}
}
}
}
}
#ifdef DEBUG_LOG
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
{
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
Uint32 rangeCount = registerAllocator.rangeCount;
SpillCost* cost = registerAllocator.spillCost;
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
for (Uint32 i = 1; i < rangeCount; i++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
if (cost[i].infinite)
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
else
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
}
}
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
{
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
Uint32 rangeCount = registerAllocator.rangeCount;
SplitCost* cost = registerAllocator.splitCost;
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
for (Uint32 i = 1; i < rangeCount; i++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
}
}
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
{
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
InstructionList& instructions = nodes[n]->getInstructions();
if (!phiNodes.empty()) {
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
phiNodes.get(i).printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
if (!instructions.empty())
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
}
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
instructions.get(i).printPretty(log);
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
}
}
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,117 @@
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
//
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
// NETSCAPE COMMUNICATIONS CORPORATION
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
// Reserved. Use of this Source Code is subject to the terms of the
// applicable license agreement from Netscape Communications Corporation.
// The copyright notice(s) in this Source Code does not indicate actual or
// intended publication of this Source Code.
//
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
//
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
#define _REGISTER_ALLOCATOR_TOOLS_H_
#include "LogModule.h"
#include "RegisterTypes.h"
#include <string.h>
class RegisterAllocator;
class ControlGraph;
class InstructionEmitter;
class VirtualRegisterManager;
struct RegisterAllocatorTools
{
//
//
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
//
//
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
//
//
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
#ifdef DEBUG
//
//
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
#endif // DEBUG
#ifdef DEBUG_LOG
//
//
static void printInstructions(RegisterAllocator& registerAllocator);
//
//
static void printSpillCosts(RegisterAllocator& registerAllocator);
//
//
static void printSplitCosts(RegisterAllocator& registerAllocator);
#endif // DEBUG_LOG
};
//
// FIX: this should go in a class (LookupTable ?)
//
inline RegisterName findRoot(RegisterName name, RegisterName* table)
{
RegisterName* stack = table;
RegisterName* stackPtr = stack;
RegisterName newName;
while((newName = table[name]) != name) {
*--stackPtr = name;
name = newName;
}
while (stackPtr != stack)
table[*stackPtr++] = name;
return name;
}
inline void init(RegisterName* table, Uint32 nameCount)
{
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
table[r] = r;
}
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
{
RegisterName* liveRange = new RegisterName[tableSize];
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
// Update the lookup table.
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
findRoot(r, table);
// Count the liveranges.
Uint32 liveRangeCount = 1;
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
if (table[s] == s)
liveRange[s] = RegisterName(liveRangeCount++);
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
name2range[t] = liveRange[table[name2range[t]]];
return liveRangeCount;
}
inline double doLog10(Uint32 power)
{
double log = 1.0;
while (power--)
log *= 10.0;
return log;
}
#endif // _REGISTER_ALLOCATOR_TOOLS_H_

View File

@@ -0,0 +1,38 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_ASSIGNER_H_
#define _REGISTER_ASSIGNER_H_
#include "Fundamentals.h"
#include "VirtualRegister.h"
class FastBitMatrix;
class RegisterAssigner
{
protected:
VirtualRegisterManager& vRegManager;
public:
RegisterAssigner(VirtualRegisterManager& vrMan) : vRegManager(vrMan) {}
virtual bool assignRegisters(FastBitMatrix& interferenceMatrix) = 0;
};
#endif /* _REGISTER_ASSIGNER_H_ */

View File

@@ -0,0 +1,25 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_CLASS_H_
#define _REGISTER_CLASS_H_
#include "Fundamentals.h"
#include "RegisterTypes.h"
#endif // _REGISTER_CLASS_H_

View File

@@ -0,0 +1,37 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_PRESSURE_H_
#define _REGISTER_PRESSURE_H_
#include "BitSet.h"
#include "HashSet.h"
struct LowRegisterPressure
{
typedef BitSet Set;
static const bool setIsOrdered = true;
};
struct HighRegisterPressure
{
typedef HashSet Set;
static const bool setIsOrdered = false;
};
#endif // _REGISTER_PRESSURE_H_

View File

@@ -0,0 +1,104 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _REGISTER_TYPES_H_
#define _REGISTER_TYPES_H_
#include "Fundamentals.h"
//------------------------------------------------------------------------------
// RegisterName -
//
enum RegisterName {
rnInvalid = 0,
};
//------------------------------------------------------------------------------
// RegisterClassKind -
//
enum RegisterClassKind {
rckInvalid = 0,
rckGeneral,
rckStackSlot,
nRegisterClassKind
};
//------------------------------------------------------------------------------
// RegisterID -
//
enum RegisterID {
invalidID = 0
};
//------------------------------------------------------------------------------
// RegisterKind -
//
enum RegisterKind {
rkCallerSave = 0,
rkCalleeSave,
};
struct NameLinkedList {
RegisterName name;
NameLinkedList* next;
};
#ifdef DEBUG
const registerNameMask = 0x03ffffff;
const coloredRegisterMask = 0x04000000;
const machineRegisterMask = 0x08000000;
const registerClassMask = 0xf0000000;
const registerNameShift = 0;
const coloredRegisterShift = 26;
const machineRegisterShift = 27;
const registerClassShift = 28;
#else // DEBUG
const registerNameMask = 0x0fffffff;
const registerClassMask = 0xf0000000;
const registerNameShift = 0;
const registerClassShift = 28;
#endif // DEBUG
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
#ifdef DEBUG
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
#endif // DEBUG
#endif // _REGISTER_TYPES_H_

View File

@@ -0,0 +1,32 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "SSATools.h"
#include "ControlGraph.h"
#include "VirtualRegister.h"
#include "Liveness.h"
void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
{
if (!controlGraph.hasBackEdges)
return;
Liveness liveness(controlGraph.pool);
liveness.buildLivenessAnalysis(controlGraph, vrManager);
}

View File

@@ -0,0 +1,29 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _SSA_TOOLS_H_
#define _SSA_TOOLS_H_
#include "Fundamentals.h"
class ControlGraph;
class VirtualRegisterManager;
extern void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
#endif // _SSA_TOOLS_H_

View File

@@ -0,0 +1,37 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "SparseSet.h"
#include "BitSet.h"
#include "Pool.h"
#ifdef DEBUG_LOG
// Print the set.
//
void SparseSet::printPretty(LogModuleObject log)
{
Pool pool;
BitSet set(pool, universeSize);
for (Uint32 i = 0; i < count; i++)
set.set(node[i].element);
set.printPretty(log);
}
#endif // DEBUG_LOG

View File

@@ -0,0 +1,168 @@
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
//
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
// NETSCAPE COMMUNICATIONS CORPORATION
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
// Reserved. Use of this Source Code is subject to the terms of the
// applicable license agreement from Netscape Communications Corporation.
// The copyright notice(s) in this Source Code does not indicate actual or
// intended publication of this Source Code.
//
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
//
#ifndef _SPARSE_SET_H_
#define _SPARSE_SET_H_
#include "Fundamentals.h"
#include "Pool.h"
#include "LogModule.h"
#include "BitSet.h"
class SparseSet
{
private:
struct Node {
Uint32 element;
Uint32 stackIndex;
};
Node* node;
Uint32 count;
Uint32 universeSize;
private:
// No copy constructor.
SparseSet(const SparseSet&);
// Check if the given set's universe is of the same size than this universe.
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
// Check if pos is valid for this set's universe.
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
public:
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
// Clear the sparse set.
void clear() {count = 0;}
// Clear the element at index.
inline void clear(Uint32 index);
// Set the element at index.
inline void set(Uint32 index);
// Return true if the element at index is set.
inline bool test(Uint32 index) const;
// Union with the given sparse set.
inline void or(const SparseSet& set);
// Intersection with the given sparse set.
inline void and(const SparseSet& set);
// Difference with the given sparse set.
inline void difference(const SparseSet& set);
// Copy set.
inline SparseSet& operator = (const SparseSet& set);
inline SparseSet& operator = (const BitSet& set);
// Return true if the sparse sets are identical.
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
// Return true if the sparse sets are different.
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
// Logical operators.
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
// Iterator to conform with the set API.
typedef Int32 iterator;
// Return the iterator for the first element of this set.
iterator begin() const {return count - 1;}
// Return the next iterator.
iterator advance(iterator pos) const {return --pos;}
// Return true if the iterator is at the end of the set.
bool done(iterator pos) const {return pos < 0;}
// Return the element for the given iterator;
Uint32 get(iterator pos) const {return node[pos].element;}
// Return one element of this set.
Uint32 getOne() const {assert(count > 0); return node[0].element;}
// Return the size of this set.
Uint32 getSize() const {return count;}
#ifdef DEBUG_LOG
// Print the set.
void printPretty(LogModuleObject log);
#endif // DEBUG_LOG
};
inline void SparseSet::clear(Uint32 element)
{
checkMember(element);
Uint32 count = this->count;
Node* node = this->node;
Uint32 stackIndex = node[element].stackIndex;
if ((stackIndex < count) && (node[stackIndex].element == element)) {
Uint32 stackTop = node[count - 1].element;
node[stackIndex].element = stackTop;
node[stackTop].stackIndex = stackIndex;
this->count = count - 1;
}
}
inline void SparseSet::set(Uint32 element)
{
checkMember(element);
Uint32 count = this->count;
Node* node = this->node;
Uint32 stackIndex = node[element].stackIndex;
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
node[count].element = element;
node[element].stackIndex = count;
this->count = count + 1;
}
}
inline bool SparseSet::test(Uint32 element) const
{
checkMember(element);
Node* node = this->node;
Uint32 stackIndex = node[element].stackIndex;
return ((stackIndex < count) && (node[stackIndex].element == element));
}
inline SparseSet& SparseSet::operator = (const SparseSet& set)
{
checkUniverseCompatibility(set);
Uint32 sourceCount = set.getSize();
Node* node = this->node;
memcpy(node, set.node, sourceCount * sizeof(Node));
for (Uint32 i = 0; i < sourceCount; i++) {
Uint32 element = node[i].element;
node[element].stackIndex = i;
}
count = sourceCount;
return *this;
}
inline SparseSet& SparseSet::operator = (const BitSet& set)
{
// FIX: there's room for optimization here.
assert(universeSize == set.getSize());
clear();
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
this->set(i);
return *this;
}
#endif // _SPARSE_SET_H_

View File

@@ -0,0 +1,270 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NEW_LAURENTM_CODE
#define INCLUDE_EMITTER
#include "CpuInfo.h"
#include "Fundamentals.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "InstructionEmitter.h"
#include "Spilling.h"
void Spilling::
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
{
PRUint32 nVirtualRegisters = vRegManager.count();
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
RegisterFifo grNeedLoad(nVirtualRegisters);
RegisterFifo fpNeedLoad(nVirtualRegisters);
for (PRInt32 n = nNodes - 1; n >= 0; n--)
{
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
ControlNode& node = *dfsList[n];
currentLive = node.liveAtEnd;
PRUint32 nGeneralAlive = 0;
PRUint32 nFloatingPointAlive = 0;
// Get the number of registers alive at the end of this node.
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
{
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
if (vReg.spillInfo.willSpill)
{
currentLive.clear(j);
}
else
{
switch (vReg.getClass())
{
case vrcInteger:
nGeneralAlive++;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
nFloatingPointAlive++;
break;
default:
break;
}
}
}
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
{
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
InstructionDefine* defPtr;
// if(node.dfsNum == 8) { printf("\n");
// instruction.printPretty(stdout);
// printf("\n"); }
// Handle definitions
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
if (defPtr->isVirtualRegister())
{
VirtualRegister& vReg = defPtr->getVirtualRegister();
currentLive.clear(vReg.getRegisterIndex());
switch (vReg.getClass())
{
case vrcInteger:
nGeneralAlive--;
break;
case vrcFloatingPoint:
case vrcFixedPoint:
nFloatingPointAlive--;
break;
default:
break;
}
}
// Check for deaths
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isVirtualRegister())
{
VirtualRegister& vReg = usePtr->getVirtualRegister();
if (!currentLive.test(vReg.getRegisterIndex()))
// This is the last use of this register.
{
currentLive.set(vReg.getRegisterIndex());
switch (vReg.getClass())
{
case vrcInteger:
nGeneralAlive++;
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
{
PRUint32 toLoad = grNeedLoad.get();
currentLive.clear(toLoad);
nGeneralAlive--;
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
nReg.releaseSelf();
}
break;
case vrcFloatingPoint:
case vrcFixedPoint:
nFloatingPointAlive++;
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
{
PRUint32 toLoad = fpNeedLoad.get();
currentLive.clear(toLoad);
nFloatingPointAlive--;
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
nReg.releaseSelf();
}
break;
default:
break;
}
}
}
// Handle uses
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isVirtualRegister())
{
VirtualRegister& vReg = usePtr->getVirtualRegister();
PRUint32 registerIndex = vReg.getRegisterIndex();
if (vReg.spillInfo.willSpill) {
#if defined(GENERATE_FOR_X86)
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
#endif
{
switch (vReg.getClass())
{
case vrcInteger:
if (!grNeedLoad.test(registerIndex))
{
grNeedLoad.put(registerIndex);
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
if (vReg.isPreColored())
alias.preColorRegister(vReg.getPreColor());
/* if (vReg.hasSpecialInterference) {
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
alias.specialInterference = vReg.specialInterference;
alias.hasSpecialInterference = true;
} */
vReg.setAlias(alias);
vReg.retainSelf();
}
break;
case vrcFloatingPoint:
case vrcFixedPoint:
if (!fpNeedLoad.test(registerIndex))
{
fpNeedLoad.put(registerIndex);
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
if (vReg.isPreColored())
alias.preColorRegister(vReg.getPreColor());
/*if (vReg.hasSpecialInterference) {
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
alias.specialInterference = vReg.specialInterference;
alias.hasSpecialInterference = true;
} */
vReg.setAlias(alias);
vReg.retainSelf();
}
break;
default:
break;
}
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
usedInThisInstruction.set(registerIndex);
vReg.spillInfo.lastUsingInstruction = &instruction;
}
currentLive.clear(registerIndex);
} else { // will not spill
currentLive.set(registerIndex);
}
}
// Handle definitions
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
if (defPtr->isVirtualRegister())
{
VirtualRegister& vReg = defPtr->getVirtualRegister();
if (vReg.spillInfo.willSpill)
#if defined(GENERATE_FOR_X86)
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
#endif
{
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
// this virtualRegister was used in this instruction and is also defined. We need to move
// this virtual register to its alias first and then save it to memory.
{
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
}
else
{
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
vReg, *vReg.equivalentRegister[vrcStackSlot]);
}
}
}
}
while (!grNeedLoad.empty())
{
PRUint32 nl = grNeedLoad.get();
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
nlReg.releaseSelf();
}
while (!fpNeedLoad.empty())
{
PRUint32 nl = fpNeedLoad.get();
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
nlReg.releaseSelf();
}
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
}
}
#endif

View File

@@ -0,0 +1,269 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _SPILLING_H_
#define _SPILLING_H_
#include "Fundamentals.h"
#include <string.h>
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "SparseSet.h"
template <class RegisterPressure>
class Spilling
{
private:
static void insertStoreAfter(Instruction& instruction, RegisterName name);
static void insertLoadBefore(Instruction& instruction, RegisterName name);
public:
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
static void insertSpillCode(RegisterAllocator& registerAllocator);
};
struct SpillCost
{
double loads;
double stores;
double copies;
double cost;
bool infinite;
};
template <class RegisterPressure>
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
{
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* name2range = registerAllocator.name2range;
Pool& pool = registerAllocator.pool;
SparseSet currentLive(pool, rangeCount);
SparseSet needLoad(pool, rangeCount);
SparseSet mustSpill(pool, rangeCount);
SparseSet& willSpill = *registerAllocator.willSpill;
ControlGraph& controlGraph = registerAllocator.controlGraph;
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
needLoad.clear();
currentLive = liveOut[n];
mustSpill = currentLive;
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
Instruction& instruction = instructions.get(i);
i = instructions.retreat(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
bool foundLiveDefine = false;
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
foundLiveDefine = true;
break;
}
} else {
foundLiveDefine = true;
break;
}
if (defineBegin != defineEnd && !foundLiveDefine) {
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
instruction.remove();
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName range = name2range[definePtr->getRegisterName()];
#ifdef DEBUG
if (needLoad.test(range))
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
abort();
}
#endif // DEBUG
if (willSpill.test(range))
insertStoreAfter(instruction, range);
needLoad.clear(range);
}
if (instruction.getFlags() & ifCopy)
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
if (!currentLive.test(range))
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
RegisterName load = RegisterName(needLoad.get(r));
if (willSpill.test(load))
insertLoadBefore(instruction, load);
mustSpill.set(load);
}
needLoad.clear();
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
currentLive.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
currentLive.set(range);
needLoad.set(range);
}
}
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
RegisterName load = RegisterName(needLoad.get(l));
if (willSpill.test(load))
insertLoadBefore(instructions.first(), load);
}
}
}
template <class RegisterPressure>
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
{
fprintf(stdout, "will insert load for range %d\n", name);
}
template <class RegisterPressure>
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
{
fprintf(stdout, "will insert store for range %d\n", name);
}
template <class RegisterPressure>
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
{
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* name2range = registerAllocator.name2range;
Pool& pool = registerAllocator.pool;
SparseSet live(pool, rangeCount);
SparseSet needLoad(pool, rangeCount);
SparseSet mustSpill(pool, rangeCount);
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
SpillCost* cost = new SpillCost[rangeCount];
memset(cost, '\0', rangeCount * sizeof(SpillCost));
ControlGraph& controlGraph = registerAllocator.controlGraph;
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
double weight = doLog10(node.loopDepth);
needLoad.clear();
live = liveOut[n];
mustSpill = live;
InstructionList& instructions = nodes[n]->getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister()) {
RegisterName range = name2range[definePtr->getRegisterName()];
if (needLoad.test(range))
if (!mustSpill.test(range))
cost[range].infinite = true;
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
cost[range].stores += weight;
needLoad.clear(range);
}
if (instruction.getFlags() & ifCopy)
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
if (!live.test(name2range[usePtr->getRegisterName()])) {
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
Uint32 range = needLoad.get(l);
cost[range].loads += weight;
mustSpill.set(range);
}
needLoad.clear();
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
live.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
live.set(range);
needLoad.set(range);
}
if (instruction.getFlags() & ifCopy) {
assert(useBegin != useEnd && useBegin[0].isRegister());
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
RegisterName source = name2range[useBegin[0].getRegisterName()];
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
cost[source].copies += weight;
cost[destination].copies += weight;
}
}
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
cost[needLoad.get(s)].loads += weight;
}
for (Uint32 r = 0; r < rangeCount; r++) {
SpillCost& c = cost[r];
c.cost = 2 * (c.loads + c.stores) - c.copies;
}
registerAllocator.spillCost = cost;
}
#endif // _SPILLING_H_

View File

@@ -0,0 +1,239 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _SPLITS_H_
#define _SPLITS_H_
#include "Fundamentals.h"
#include <string.h>
#include "Pool.h"
#include "ControlGraph.h"
#include "ControlNodes.h"
#include "Instruction.h"
#include "RegisterAllocator.h"
#include "RegisterAllocatorTools.h"
UT_EXTERN_LOG_MODULE(RegAlloc);
template <class RegisterPressure>
struct Splits
{
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
static void insertSplitCode(RegisterAllocator& registerAllocator);
};
struct SplitCost
{
double loads;
double stores;
};
template <class RegisterPressure>
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
{
// FIX
}
template <class RegisterPressure>
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
{
Pool& pool = registerAllocator.pool;
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
for (Int32 i = vector->count - 1; i >=0; --i) {
RegisterName neighbor = vector->neighbors[i];
RegisterName c = color[neighbor];
if (c < 6) { // FIX
NameLinkedList* node = new(pool) NameLinkedList();
node->name = neighbor;
node->next = neighborsWithColor[c];
neighborsWithColor[c] = node;
}
}
bool splitAroundName = true;
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
RegisterName bestColor = RegisterName(6); // FIX
double bestCost = registerAllocator.spillCost[range].cost;
SplitCost* splitCost = registerAllocator.splitCost;
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
double splitAroundNameCost = 0.0;
bool canSplitAroundName = true;
SplitCost& sCost = splitCost[range];
double addedCost = 2.0 * (sCost.stores + sCost.loads);
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
RegisterName neighbor = node->name;
if (lGraph.haveEdge(neighbor, range)) {
canSplitAroundName = false;
break;
} else
splitAroundNameCost += addedCost;
}
if (canSplitAroundName && splitAroundNameCost < bestCost) {
bestCost = splitAroundNameCost;
bestColor = i;
splitAroundName = true;
}
double splitAroundColorCost = 0.0;
bool canSplitAroundColor = true;
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
RegisterName neighbor = node->name;
if (lGraph.haveEdge(range, neighbor)) {
canSplitAroundColor = false;
break;
} else {
SplitCost& sCost = splitCost[neighbor];
double addedCost = 2.0 * (sCost.stores + sCost.loads);
splitAroundColorCost += addedCost;
}
}
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
bestCost = splitAroundColorCost;
bestColor = i;
splitAroundName = false;
}
}
if (bestColor < RegisterName(6)) {
color[range] = bestColor;
registerAllocator.splitFound = true;
NameLinkedList** splitAround = registerAllocator.splitAround;
if (splitAroundName)
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
NameLinkedList* newNode = new(pool) NameLinkedList();
newNode->name = node->name;
newNode->next = splitAround[range];
splitAround[range] = newNode;
}
else
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
NameLinkedList* newNode = new(pool) NameLinkedList();
RegisterName neighbor = node->name;
newNode->name = range;
newNode->next = splitAround[neighbor];
splitAround[neighbor] = newNode;
}
trespass("Found a split");
return true;
}
return false;
}
template <class RegisterPressure>
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
{
Pool& pool = registerAllocator.pool;
Uint32 rangeCount = registerAllocator.rangeCount;
RegisterName* name2range = registerAllocator.name2range;
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
SparseSet live(pool, rangeCount);
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
ControlGraph& controlGraph = registerAllocator.controlGraph;
ControlNode** nodes = controlGraph.dfsList;
Uint32 nNodes = controlGraph.nNodes;
for (Uint32 n = 0; n < nNodes; n++) {
ControlNode& node = *nodes[n];
double weight = doLog10(node.loopDepth);
live = liveOut[n];
ControlEdge* successorsEnd = node.getSuccessorsEnd();
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
ControlNode& successor = successorsPtr->getTarget();
if (successor.getControlKind() != ckEnd) {
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
RegisterName name = RegisterName(live.get(i));
if (!successorLiveIn.test(name))
splitCost[name].loads += doLog10(successor.loopDepth);
}
}
}
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
Instruction& instruction = instructions.get(i);
InstructionUse* useBegin = instruction.getInstructionUseBegin();
InstructionUse* useEnd = instruction.getInstructionUseEnd();
InstructionUse* usePtr;
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
InstructionDefine* definePtr;
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister()) {
RegisterName range = name2range[usePtr->getRegisterName()];
if (!live.test(range)) {
if (&instruction != &instructions.last())
splitCost[range].loads += weight;
else {
ControlEdge* successorsEnd = node.getSuccessorsEnd();
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
}
}
}
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
if (definePtr->isRegister())
live.clear(name2range[definePtr->getRegisterName()]);
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
if (usePtr->isRegister())
live.set(name2range[usePtr->getRegisterName()]);
}
}
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
registerAllocator.splitAround = splitAround;
registerAllocator.splitCost = splitCost;
registerAllocator.splitFound = false;
}
#endif // _SPLITS_H_

View File

@@ -0,0 +1,186 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "HashTable.h"
#include "Timer.h"
#include "Pool.h"
static Pool pool; // Pool for the Timer class.
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
const nTimersInABlock = 128; // Number of timers in a block.
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
static Uint8 nextTimer = 0; // nextAvailableTimer.
//
// Calibrate the call to PR_Now().
//
static PRTime calibrate()
{
PRTime t = PR_Now();
PRTime& a = *new(pool) PRTime();
// Call 10 times the PR_Now() function.
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
t = (PR_Now() - t + 9) / 10;
return t;
}
static PRTime adjust = calibrate();
//
// Return the named timer..
//
TimerEntry& Timer::getTimerEntry(const char* name)
{
if (!timerEntries.exists(name)) {
TimerEntry* newEntry = new(pool) TimerEntry();
newEntry->accumulator = 0;
newEntry->running = false;
timerEntries.add(name, newEntry);
}
return *timerEntries[name];
}
//
// Return a reference to a new timer.
//
PRTime& Timer::getNewTimer()
{
if (nextTimer >= nTimersInABlock) {
timers = new(pool) PRTime[nTimersInABlock];
nextTimer = 0;
}
return timers[nextTimer++];
}
static Uint32 timersAreFrozen = 0;
//
// Start the named timer.
//
void Timer::start(const char* name)
{
if (timersAreFrozen)
return;
freezeTimers();
TimerEntry& timer = getTimerEntry(name);
PR_ASSERT(!timer.running);
timer.accumulator = 0;
timer.running = true;
timer.done = false;
unfreezeTimers();
}
//
// Stop the named timer.
//
void Timer::stop(const char* name)
{
if (timersAreFrozen)
return;
freezeTimers();
TimerEntry& timer = getTimerEntry(name);
PR_ASSERT(timer.running);
timer.running = false;
timer.done = true;
unfreezeTimers();
}
//
// Freeze all the running timers.
//
void Timer::freezeTimers()
{
PRTime when = PR_Now() - adjust;
if (timersAreFrozen == 0) {
Vector<TimerEntry*> entries = timerEntries;
Uint32 count = entries.size();
for (Uint32 i = 0; i < count; i++) {
TimerEntry& entry = *entries[i];
if (entry.running) {
entry.accumulator += (when - *entry.startTime);
}
}
}
timersAreFrozen++;
}
//
// Unfreeze all the running timers.
//
void Timer::unfreezeTimers()
{
PR_ASSERT(timersAreFrozen != 0);
timersAreFrozen--;
if (timersAreFrozen == 0) {
Vector<TimerEntry *> entries = timerEntries;
Uint32 count = entries.size();
PRTime& newStart = getNewTimer();
for (Uint32 i = 0; i < count; i++) {
TimerEntry& entry = *entries[i];
if (entry.running) {
entry.startTime = &newStart;
}
}
newStart = PR_Now();
}
}
//
// Print the named timer in the file f.
//
void Timer::print(FILE* f, const char *name)
{
if (timersAreFrozen)
return;
freezeTimers();
TimerEntry& timer = getTimerEntry(name);
PR_ASSERT(timer.done);
PRTime elapsed = timer.accumulator;
if (elapsed >> 32) {
fprintf(f, "[timer %s out of range]\n", name);
} else {
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
}
fflush(f);
unfreezeTimers();
}

View File

@@ -0,0 +1,80 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _TIMER_H_
#define _TIMER_H_
#include "Fundamentals.h"
#include "HashTable.h"
#include "prtime.h"
//
// Naming convention:
// As the class Timer contains only static methods, the timer's name should start with the
// module name. Otherwise starting 2 timers with the same name will assert.
//
#ifndef NO_TIMER
struct TimerEntry
{
PRTime *startTime; // Current time when we start the timer.
PRTime accumulator; // Time spent in this timer.
bool running; // True if the timer is running.
bool done; // True if the timer was running and was stopped.
};
class Timer
{
private:
// Return the named timer.
static TimerEntry& getTimerEntry(const char* name);
// Return a reference to a new Timer.
static PRTime& getNewTimer();
public:
// Start the timer.
static void start(const char* name);
// Stop the timer.
static void stop(const char* name);
// Freeze all the running timers.
static void freezeTimers();
// Unfreeze all the running timers.
static void unfreezeTimers();
// Print the timer.
static void print(FILE* f, const char *name);
};
inline void startTimer(const char* name) {Timer::start(name);}
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
#define START_TIMER_SAFE Timer::freezeTimers();
#define END_TIMER_SAFE Timer::unfreezeTimers();
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
#else /* NO_TIMER */
inline void startTimer(const char* /*name*/) {}
inline void stopTimer(const char* /*name*/) {}
#define START_TIMER_SAFE
#define END_TIMER_SAFE
#define TIMER_SAFE(x) x;
#endif /* NO_TIMER */
#endif /* _TIMER_H_ */

View File

@@ -0,0 +1,40 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "Fundamentals.h"
#include "VirtualRegister.h"
#include "Instruction.h"
//------------------------------------------------------------------------------
// VirtualRegister -
#ifdef MANUAL_TEMPLATES
template class IndexedPool<VirtualRegister>;
#endif
// Set the defining instruction.
//
void VirtualRegister::setDefiningInstruction(Instruction& instruction)
{
if (definingInstruction != NULL) {
if ((instruction.getFlags() & ifCopy) && (definingInstruction->getFlags() & ifPhiNode))
return;
}
definingInstruction = &instruction;
}

View File

@@ -0,0 +1,116 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _VIRTUAL_REGISTER_H_
#define _VIRTUAL_REGISTER_H_
#include "Fundamentals.h"
#include "IndexedPool.h"
#include <string.h>
#include "RegisterTypes.h"
#include "RegisterClass.h"
//------------------------------------------------------------------------------
// VirtualRegister - 24b
class Instruction;
class VirtualRegister : public IndexedObject<VirtualRegister>
{
public:
Instruction* definingInstruction; // Instruction defining this VR.
// Initialize a VR of the given classKind.
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
// Return the defining instruction for this VR.
Instruction* getDefiningInstruction() const {return definingInstruction;}
// Set the defining instruction.
void setDefiningInstruction(Instruction& insn);
};
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
// they have the same index. If they have the same index then they are at the same
// address in the indexed pool.
//
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return &regA == &regB;}
//------------------------------------------------------------------------------
// VirtualRegisterManager -
struct PreColoredRegister
{
RegisterID id;
RegisterName color;
};
class VirtualRegisterManager
{
private:
IndexedPool<VirtualRegister> registerPool;
PreColoredRegister machineRegister[6];
public:
VirtualRegisterManager()
{
for (Uint32 i = 0; i < 6; i++)
machineRegister[i].id = invalidID;
}
// Return the VirtualRegister at the given index.
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
// Return a new VirtualRegister.
RegisterID newVirtualRegister(RegisterClassKind classKind)
{
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
RegisterID rid;
setName(rid, RegisterName(vReg.getIndex()));
setClass(rid, classKind);
return rid;
}
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
{
RegisterID rid = machineRegister[name].id;
if (rid == invalidID) {
rid = newVirtualRegister(classKind);
DEBUG_ONLY(setMachineRegister(rid));
machineRegister[name].id = rid;
machineRegister[name].color = name;
}
return rid;
}
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
// Return the VirtualRegister universe size.
Uint32 getSize() {return registerPool.getSize();}
void setSize(Uint32 size) {registerPool.setSize(size);}
};
#endif // _VIRTUAL_REGISTER_H_

View File

@@ -1,88 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
# have to put this here, instead of in rules.mk, so that Java gets
# built first
all:: buildJava
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
include rules.mk
build_coreconf:
cd $(CORE_DEPTH)/coreconf ; $(MAKE)
package:
$(MAKE) -C pkg publish

View File

@@ -1,295 +0,0 @@
#use strict;
use File::Find;
use File::Compare;
use File::Basename;
use File::stat;
use File::Copy;
@excluded_sources = qw(
provider\.new/
org/mozilla/jss/provider/java/security/KeyFactorySpi1_4\.java
org/mozilla/jss/pkix/cert/X509Certificate\.java
samples/
);
@javah_classes = qw(
org.mozilla.jss.DatabaseCloser
org.mozilla.jss.CryptoManager
org.mozilla.jss.crypto.Algorithm
org.mozilla.jss.crypto.EncryptionAlgorithm
org.mozilla.jss.crypto.PQGParams
org.mozilla.jss.crypto.SecretDecoderRing
org.mozilla.jss.pkcs11.CertProxy
org.mozilla.jss.pkcs11.CipherContextProxy
org.mozilla.jss.pkcs11.PK11Module
org.mozilla.jss.pkcs11.ModuleProxy
org.mozilla.jss.pkcs11.PK11Cert
org.mozilla.jss.pkcs11.PK11Cipher
org.mozilla.jss.pkcs11.PK11KeyWrapper
org.mozilla.jss.pkcs11.PK11MessageDigest
org.mozilla.jss.pkcs11.PK11PrivKey
org.mozilla.jss.pkcs11.PK11PubKey
org.mozilla.jss.pkcs11.PK11SymKey
org.mozilla.jss.pkcs11.PK11KeyPairGenerator
org.mozilla.jss.pkcs11.PK11KeyGenerator
org.mozilla.jss.pkcs11.PK11Token
org.mozilla.jss.pkcs11.PrivateKeyProxy
org.mozilla.jss.pkcs11.PublicKeyProxy
org.mozilla.jss.pkcs11.SymKeyProxy
org.mozilla.jss.pkcs11.KeyProxy
org.mozilla.jss.pkcs11.PK11Token
org.mozilla.jss.pkcs11.TokenProxy
org.mozilla.jss.pkcs11.PK11Signature
org.mozilla.jss.pkcs11.PK11Store
org.mozilla.jss.pkcs11.PK11KeyPairGenerator
org.mozilla.jss.pkcs11.SigContextProxy
org.mozilla.jss.pkcs11.PK11RSAPublicKey
org.mozilla.jss.pkcs11.PK11DSAPublicKey
org.mozilla.jss.pkcs11.PK11SecureRandom
org.mozilla.jss.provider.java.security.JSSKeyStoreSpi
org.mozilla.jss.SecretDecoderRing.KeyManager
org.mozilla.jss.ssl.SSLSocket
org.mozilla.jss.ssl.SSLServerSocket
org.mozilla.jss.ssl.SocketBase
org.mozilla.jss.util.Debug
org.mozilla.jss.util.Password
);
@packages = qw(
org.mozilla.jss
org.mozilla.jss.asn1
org.mozilla.jss.crypto
org.mozilla.jss.pkcs7
org.mozilla.jss.pkcs10
org.mozilla.jss.pkcs11
org.mozilla.jss.pkcs12
org.mozilla.jss.pkix.primitive
org.mozilla.jss.pkix.cert
org.mozilla.jss.pkix.cmc
org.mozilla.jss.pkix.cmmf
org.mozilla.jss.pkix.cms
org.mozilla.jss.pkix.crmf
org.mozilla.jss.provider.java.security
org.mozilla.jss.provider.javax.crypto
org.mozilla.jss.SecretDecoderRing
org.mozilla.jss.ssl
org.mozilla.jss.tests
org.mozilla.jss.util
);
# setup variables
setup_vars(\@ARGV);
# run the command with its arguments
my $cmd = (shift || "build"); # first argument is command
grep { s/(.*)/"$1"/ } @ARGV; # enclose remaining arguments in quotes
my $args = join(",",@ARGV); # and comma-separate them
eval "$cmd($args)"; # now run the command
if( $@ ) {
die $@; # errors in eval will be put in $@
}
# END
sub grab_cmdline_vars {
my $argv = shift;
while( $$argv[0] =~ /(.+)=(.*)/ ) {
$cmdline_vars{$1} = $2;
shift @$argv;
}
}
sub dump_cmdline_vars {
print "Command variables:\n";
for(keys %cmdline_vars) {
print "$_=" . $cmdline_vars{$_} . "\n";
}
}
sub setup_vars {
my $argv = shift;
grab_cmdline_vars($argv);
dump_cmdline_vars();
$ENV{JAVA_HOME} or die "Must specify JAVA_HOME environment variable";
$javac = "$ENV{JAVA_HOME}/bin/javac";
$javah = "$ENV{JAVA_HOME}/bin/javah";
$javadoc = "$ENV{JAVA_HOME}/bin/javadoc";
$dist_dir = $cmdline_vars{SOURCE_PREFIX};
$jce_jar = $ENV{JCE_JAR};
$class_release_dir = $cmdline_vars{SOURCE_RELEASE_PREFIX};
if( $ENV{BUILD_OPT} ) {
$class_dir = "$dist_dir/classes";
$class_jar = "$dist_dir/$cmdline_vars{XPCLASS_JAR}";
$class_release_dir .= "/$cmdline_vars{SOURCE_RELEASE_CLASSES_DIR}";
$javac_opt_flag = "-O";
$debug_source_file = "org/mozilla/jss/util/Debug_ship.jnot";
} else {
$class_dir = "$dist_dir/classes_DBG";
$class_jar = "$dist_dir/$cmdline_vars{XPCLASS_DBG_JAR}";
$class_release_dir .= "/$cmdline_vars{SOURCE_RELEASE_CLASSES_DBG_DIR}";
$javac_opt_flag = "-g";
$debug_source_file = "org/mozilla/jss/util/Debug_debug.jnot";
}
$jni_header_dir = "$dist_dir/private/jss/_jni";
if( $jce_jar ) {
$classpath = "-classpath $jce_jar";
}
}
sub clean {
print_do("rm -rf $class_dir");
print_do("rm -f $class_jar");
print_do("rm -rf $jni_header_dir");
}
sub build {
#
# copy the appropriate debug file
#
my $debug_target_file = "org/mozilla/jss/util/Debug.java";
if( compare($debug_source_file, $debug_target_file) ) {
copy($debug_source_file, $debug_target_file) or die "Copying file: $!";
}
#
# recursively find *.java
#
my %source_list;
find sub {
my $name = $File::Find::name;
if( $name =~ /\.java$/) {
$source_list{$File::Find::name} = 1;
}
}, ".";
#
# weed out files that are excluded or don't need to be updated
#
my $file;
foreach $file (keys %source_list) {
my $pattern;
foreach $pattern (@excluded_sources) {
if( $file =~ /$pattern/ ) {
delete $source_list{$file};
}
}
unless( java_source_needs_update( $file, $class_dir ) ){
delete $source_list{$file};
}
}
my @source_list = keys(%source_list);
#
# build the java sources
#
if( scalar(@source_list) > 0 ) {
ensure_dir_exists($class_dir);
print_do("$javac $javac_opt_flag -sourcepath . -d $class_dir " .
"$classpath " . join(" ",@source_list));
print_do("sh -c 'pwd && cd $class_dir && pwd && rm -f $class_jar && pwd && ls -al && ls -al ../../dist && zip -r $class_jar *'");
print "Exit status was " . ($?>>8) . "\n";
}
#
# create the JNI header files
#
ensure_dir_exists($jni_header_dir);
print_do("$javah -classpath $class_dir -d $jni_header_dir " .
(join " ", @javah_classes) );
}
sub print_do {
my $cmd = shift;
print "$cmd\n";
system($cmd);
my $exit_status = $?>>8;
$exit_status and die "Command failed ($exit_status)\n";
}
sub needs_update {
my $target = shift;
my @dependencies = @_;
my $target_mtime = (stat($target))[9];
my $dep;
foreach $dep( @dependencies ) {
my $dep_mtime = (stat($dep))[9];
if( $dep_mtime > $target_mtime ) {
return 1;
}
}
return 0;
}
# A quick-and-dirty way to guess whether a .java file needs to be rebuilt.
# We merely look for a .class file of the same name. This won't work if
# the source file's directory is different from its package, and it
# doesn't know about nested or inner classes.
# source_file: the relative path to the source file ("org/mozilla/jss/...")
# dest_dir: the directory where classes are output ("../../dist/classes_DBG")
# Returns 1 if the source file is newer than the class file, or the class file
# doesn't exist. Returns 0 if the class file is newer than the source file.
sub java_source_needs_update {
my $source_file = shift;
my $dest_dir = shift;
my $class_dir = "$dest_dir/" . dirname($source_file);
my $class_file = basename($source_file);
$class_file =~ s/\.java/.class/;
$class_file = $class_dir . "/" . $class_file;
if( -f $class_file ) {
my $class_stat = stat($class_file);
my $source_stat = stat($source_file);
if( $source_stat->mtime > $class_stat->mtime) {
# class file exists and is out of date
return 1;
} else {
#class file exists and is up to date
return 0;
}
} else {
# class file hasn't been generated yet.
return 1;
}
}
# Recursively makes the given directory. Dies at the first sign of trouble
sub ensure_dir_exists {
my $dir = shift;
my $parent = dirname($dir);
if( $parent ne $dir ) {
ensure_dir_exists($parent);
}
if( ! -d $dir ) {
mkdir($dir, 0777) or die "Failed to mkdir $dir: $!";
}
}
sub release {
# copy all class files into release directory
ensure_dir_exists("$class_release_dir");
print_do("cp -r $class_dir/* $class_release_dir");
}
sub javadoc {
my $html_header_opt;
if( $ENV{HTML_HEADER} ) {
$html_header_opt = "-header '$ENV{HTML_HEADER}'";
}
ensure_dir_exists("$dist_dir/jssdoc");
my $targets = join(" ", @packages);
print "$targets\n";
print_do("$javadoc -breakiterator -sourcepath . -d $dist_dir/jssdoc $html_header_opt $targets");
print_do("cp $dist_dir/jssdoc/index.html $dist_dir/jssdoc/index.html.bak");
print_do("cp $dist_dir/jssdoc/overview-summary.html $dist_dir/jssdoc/index.html");
}

View File

@@ -1,73 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#
# Configuration information unique to the "sectools" component
#
#######################################################################
# Local "sectools" component library link options #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/linkage.mk
#######################################################################
# Local "sectools" component STATIC system library names #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/static.mk
#######################################################################
# Local "sectools" component DYNAMIC system library names #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/dynamic.mk
# Stricter semantic checking for SunOS compiler. This catches calling
# undeclared functions, a major headache during debugging.
ifeq ($(OS_ARCH), SunOS)
OS_CFLAGS += -v
endif
ifeq ($(OS_ARCH), WINNT)
LINK_DLL += -LIBPATH:$(SOURCE_LIB_DIR)
LINK_DLL += -LIBPATH:$(JAVA_HOME)/$(JAVA_LIBDIR)
LINK_DLL += $(foreach file,$(LD_LIBS),-DEFAULTLIB:"$(notdir $(file))")
endif
CFLAGS += -I$(JAVA_HOME)/include

View File

@@ -1,150 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# Initialize DYNAMIC system library names on some platforms #
#######################################################################
#
# AIX platforms
#
ifeq ($(OS_ARCH),AIX)
ifeq ($(OS_RELEASE),4.1)
DLLSYSTEM += -lsvld -lC_r -lC -lpthreads -lc_r -lm /usr/lib/libc.a
else
DLLSYSTEM += -ldl -lC_r -lC -lpthreads -lc_r -lm /usr/lib/libc.a
endif
endif
#
# HP/UX platforms
#
ifeq ($(OS_ARCH),HP-UX)
ifeq ($(USE_PTHREADS), 1)
DLLSYSTEM += -lpthread
endif
ifeq ($(PTHREADS_USER), 1)
DLLSYSTEM += -lpthread
endif
ifeq ($(OS_RELEASE),A.09.03)
DLLSYSTEM += -ldld -L/lib/pa1.1 -lm
else
DLLSYSTEM += -ldld -lm -lc
endif
endif
#
# IRIX platforms
#
ifeq ($(OS_ARCH), IRIX)
ifeq ($(USE_PTHREADS), 1)
DLLSYSTEM += -lpthread
endif
endif
#
# Linux platforms
#
ifeq ($(OS_ARCH), Linux)
DLLSYSTEM += -ldl -lpthread -lm
endif
#
# NCR platforms
#
ifeq ($(OS_ARCH), NCR)
DLLSYSTEM += -lsocket -ldl -lnsl -lc
endif
#
# OSF 1 platforms
#
ifeq ($(OS_ARCH),OSF1)
ifneq ($(OS_RELEASE),V2.0)
DLLSYSTEM += -lc_r
endif
ifeq ($(USE_PTHREADS), 1)
DLLSYSTEM += -lpthread -lrt
endif
ifeq ($(USE_IPV6), 1)
DLLSYSTEM += -lip6
endif
endif
#
# SCO platforms
#
ifeq ($(OS_ARCH), SCO_SV)
DLLSYSTEM += -lsocket -ldl -lnsl -lc
endif
#
# Solaris platforms
#
ifeq ($(OS_ARCH), SunOS)
ifneq ($(OS_RELEASE), 4.1.3_U1)
DLLSYSTEM += -lthread -lposix4 -lsocket -lnsl -lintl -ldl
endif
endif
#
# UNIXWARE platforms
#
ifeq ($(OS_ARCH), UNIXWARE)
DLLSYSTEM += -lsocket
endif
#
# Windows platforms
#
ifeq ($(OS_ARCH),WINNT)
ifneq ($(OS_TARGET),WIN16)
DLLSYSTEM += wsock32.lib winmm.lib
endif
endif

View File

@@ -1,98 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# Adjust variables for component library linkage on some platforms #
#######################################################################
#
# AIX platforms
#
ifeq ($(OS_ARCH),AIX)
LDOPTS += -blibpath:.:$(PWD)/$(SOURCE_LIB_DIR):/usr/lib/threads:/usr/lpp/xlC/lib:/usr/lib:/lib
endif
#
# HP/UX platforms
#
ifeq ($(OS_ARCH), HP-UX)
LDOPTS += -Wl,+s,+b,$(PWD)/$(SOURCE_LIB_DIR)
endif
#
# IRIX platforms
#
ifeq ($(OS_ARCH), IRIX)
LDOPTS += -rpath $(PWD)/$(SOURCE_LIB_DIR)
endif
#
# OSF 1 platforms
#
ifeq ($(OS_ARCH), OSF1)
LDOPTS += -rpath $(PWD)/$(SOURCE_LIB_DIR) -lpthread
endif
#
# Solaris platforms
# NOTE: Disable optimization on SunOS4.1.3
#
ifeq ($(OS_ARCH), SunOS)
ifneq ($(OS_RELEASE), 4.1.3_U1)
ifdef NS_USE_GCC
LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(SOURCE_LIB_DIR)
else
LDOPTS += -R $(PWD)/$(SOURCE_LIB_DIR)
endif
else
OPTIMIZER =
endif
endif
#
# Windows platforms
#
ifeq ($(OS_ARCH), WINNT)
LDOPTS += -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
endif

View File

@@ -1,43 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
### ###
### R U L E S O F E N G A G E M E N T ###
### ###
#######################################################################

View File

@@ -1,142 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# Initialize STATIC system library names on some platforms #
#######################################################################
#
# AIX platforms
#
ifeq ($(OS_ARCH),AIX)
ifeq ($(OS_RELEASE),4.1)
LIBSYSTEM += /lib/libsvld.a /lib/libC_r.a /lib/libC.a /lib/libpthreads.a /lib/libc_r.a /lib/libm.a /lib/libc.a
else
LIBSYSTEM += -ldl /lib/libC_r.a /lib/libC.a /lib/libpthreads.a /lib/libc_r.a /lib/libm.a /lib/libc.a
endif
endif
#
# HP/UX platforms
#
ifeq ($(OS_ARCH),HP-UX)
ifeq ($(USE_PTHREADS), 1)
LIBSYSTEM += -lpthread
endif
ifeq ($(PTHREADS_USER), 1)
LIBSYSTEM += -lpthread
endif
ifeq ($(OS_RELEASE),A.09.03)
LIBSYSTEM += -ldld -L/lib/pa1.1 -lm
else
LIBSYSTEM += -ldld -lm -lc
endif
endif
#
# Linux platforms
#
ifeq ($(OS_ARCH), Linux)
LIBSYSTEM += -ldl
endif
#
# IRIX platforms
#
ifeq ($(OS_ARCH), IRIX)
ifeq ($(USE_PTHREADS), 1)
LIBSYSTEM += -lpthread
endif
endif
#
# OSF 1 platforms
#
ifeq ($(OS_ARCH),OSF1)
ifneq ($(OS_RELEASE),V2.0)
LIBSYSTEM += -lc_r
endif
ifeq ($(USE_PTHREADS), 1)
LIBSYSTEM += -lpthread -lrt
endif
ifeq ($(USE_IPV6), 1)
LIBSYSTEM += -lip6
endif
endif
#
# Solaris platforms
#
ifeq ($(OS_ARCH), SunOS)
ifneq ($(OS_RELEASE), 4.1.3_U1)
ifeq ($(OS_RELEASE), 5.5.1_i86pc)
LIBSYSTEM += -lsocket -lnsl -lintl -ldl
else
ifeq ($(OS_RELEASE), 5.6_i86pc)
LIBSYSTEM += -lsocket -lnsl -lintl -ldl
else
LIBSYSTEM += -lthread -lposix4 /lib/libsocket.a /lib/libnsl.a /lib/libintl.a -ldl
endif
endif
endif
endif
#
# UNIXWARE platforms
#
ifeq ($(OS_ARCH), UNIXWARE)
LIBSYSTEM += -lsocket
endif
#
# Windows platforms
#
ifeq ($(OS_ARCH),WINNT)
ifneq ($(OS_TARGET),WIN16)
LIBSYSTEM += wsock32.lib winmm.lib
endif
endif

View File

@@ -1,100 +0,0 @@
<html>
<!-- ***** 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 Services for Java.
-
- The Initial Developer of the Original Code is
- Netscape Communications Corporation.
- 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 ***** -->
<head>
<title>Netscape Security Services for Java</title>
</head>
<body bgcolor="white" text="black">
<!--font face="sans-serif"-->
<center><h1>Netscape Security Services for Java</h1></center>
Netscape Security Services for Java (JSS) is an interface allowing Java applications
to use the Secure Sockets Layer protocol. The interface is implemented with the
FIPS-validated Netscape Security Services library.
It consists of a system-dependent dynamic library (<code>libjss.so</code>
on UNIX, <code>jss.dll</code> on Windows) and a ZIP file
(<code>jss.zip</code>) containing system-independent Java classes.
These classes are compatible with JDK 1.1 or later <b>using the native
thread implementation (not green threads)</b>.
<h2>Building Applications with JSS</h2>
To construct Java applications that use JSS, you must:
<ul>
<li>Call the JSS classes from your application.
<li>When compiling your application, put <code>jss.zip</code> in your
<code>CLASSPATH</code>.
<li>When running your application, put <code>libjss.so</code> in your
<code>LD_LIBRARY_PATH</code> (on UNIX) or <code>jss.dll</code>
in your <code>PATH</code> (on Windows), and put
<code>jss.zip</code> in your <code>CLASSPATH</code>.
</ul>
<h2>Programming with JSS</h2>
Before the SSL classes can be used,
<a href="javadoc/org/mozilla/jss/NSSInit.html#initialize(java.lang.String, java.lang.String, java.lang.String)">
<code>NSSInit.initialize</code></a> must be called to open the security
databases and initialize the random number generator.
<a href="javadoc/org/mozilla/jss/NSSInit.html#setPasswordCallback(org.mozilla.jss.util.PasswordCallback)"><code>
NSSInit.setPasswordCallback</code></a> may be called to change the password
callback; the default is to prompt for passwords on the command line.
<p>The files in the <code>examples</code> directory illustrate the use of JSS
in an application:
<dl>
<dt><a href="examples/SSLClient.java">SSLClient.java</a>
<dd>An example of an SSL client application.
<dt><a href="examples/SSLServer.java">SSLServer.java</a>
<dd>An example of an SSL server application.
To run, it requires certificate
and key databases that contain a certificate called "SSLServer". The sample
<code>cert7.db</code> and <code>key3.db</code> files, also in the
<code>examples</code> directory,
can be used for this purpose. When <code>SSLServer</code> is run,
it will ask for a password
for the "Internal Key Storage Token", which is the key database.
The password for the example <code>key3.db</code> file is "netscape".
</dl>
These classes are in the <code>org.mozilla.jss.ssl</code> package.
The <code>.class</code> files must be put in the subdirectory
<code>org/mozilla/jss/ssl</code> of a <code>CLASSPATH</code> entry
in order to be located by the Java virtual machine.
<a href="javadoc/index.html"><h2>Javadoc for the JSS Classes</h2></a>
<!--/font-->
</body>
</html>

View File

@@ -1,79 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/config.mk
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/rules.mk
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
include rules.mk

View File

@@ -1,127 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
LIBRARY =
SHARED_LIBRARY_LIBS=yes
SHARED_LIBRARY_DIRS = \
../org/mozilla/jss/crypto \
../org/mozilla/jss/SecretDecoderRing \
../org/mozilla/jss \
../org/mozilla/jss/pkcs11 \
../org/mozilla/jss/ssl \
../org/mozilla/jss/util \
../org/mozilla/jss/provider/java/security \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll
IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib
DLLFLAGS += -DEF:jss.def
RES = $(OBJDIR)/jss.res
RESNAME = jss.rc
EXTRA_SHARED_LIBS += \
$(DIST)/lib/nss3.lib \
$(DIST)/lib/smime3.lib \
$(DIST)/lib/ssl3.lib \
$(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \
$(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \
$(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \
$(JAVA_LIBS) \
$(DLLSYSTEM) \
$(NULL)
else
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-lnss3 \
-lsmime3 \
-lssl3 \
-lplc4 \
-lplds4 \
-lnspr4 \
$(JAVA_LIBS) \
$(NULL)
endif
# Include "funky" link path to pick up ALL native libraries for OSF/1.
ifeq ($(OS_ARCH), OSF1)
JAVA_LIBS += -L$(JAVA_HOME)/$(JAVA_LIBDIR).no
endif
ifeq ($(OS_ARCH),Linux)
MAPFILE = $(OBJDIR)/jssmap.linux
ALL_TRASH += $(MAPFILE)
MKSHLIB += -Wl,--version-script,$(MAPFILE)
endif
ifeq ($(OS_ARCH),SunOS)
MAPFILE = $(OBJDIR)/jssmap.sun
ALL_TRASH += $(MAPFILE)
MKSHLIB += -M $(MAPFILE)
#ifndef USE_64
#ifeq ($(CPU_ARCH),sparc)
# The -R '$ORIGIN' linker option instructs libnss3.so to search for its
# dependencies (libfreebl_*.so) in the same directory where it resides.
#MKSHLIB += -R '$$ORIGIN'
#endif
#endif
endif
ifeq ($(OS_ARCH),AIX)
MAPFILE = $(OBJDIR)/jssmap.aix
ALL_TRASH += $(MAPFILE)
EXPORT_RULES = -bexport:$(MAPFILE)
endif
ifeq ($(OS_ARCH),HP-UX)
MAPFILE = $(OBJDIR)/jssmap.hp
ALL_TRASH += $(MAPFILE)
MKSHLIB += -c $(MAPFILE)
endif
ifeq ($(OS_ARCH), OSF1)
MAPFILE = $(OBJDIR)/jssmap.osf
ALL_TRASH += $(MAPFILE)
MKSHLIB += -hidden -input $(MAPFILE)
endif

View File

@@ -1,281 +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) 2001 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.
;+#
;+#
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
;+# 1. For all unix platforms, the string ";-" means "remove this line"
;+# 2. For all unix platforms, the string " DATA " will be removed from any
;+# line on which it occurs.
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
;+# On AIX, lines containing ";+" will be removed.
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
;+# 5. For all unix platforms, after the above processing has taken place,
;+# all characters after the first ";" on the line will be removed.
;+# And for AIX, the first ";" will also be removed.
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
;+# directives are hidden behind ";", ";+", and ";-"
;+JSS_3.0 { # JSS 3.0 release
;+ global:
LIBRARY jss3 ;-
EXPORTS ;-
Java_org_mozilla_jss_crypto_EncryptionAlgorithm_getIVLength;
Java_org_mozilla_jss_crypto_PQGParams_generateNative__I;
Java_org_mozilla_jss_crypto_PQGParams_generateNative__II;
Java_org_mozilla_jss_crypto_PQGParams_paramsAreValidNative;
Java_org_mozilla_jss_DatabaseCloser_closeDatabases;
Java_org_mozilla_jss_CryptoManager_FIPSEnabled;
Java_org_mozilla_jss_CryptoManager_buildCertificateChainNative;
Java_org_mozilla_jss_CryptoManager_enableFIPS;
Java_org_mozilla_jss_CryptoManager_exportCertsToPKCS7;
Java_org_mozilla_jss_CryptoManager_findCertByIssuerAndSerialNumberNative;
Java_org_mozilla_jss_CryptoManager_findCertByNicknameNative;
Java_org_mozilla_jss_CryptoManager_findCertsByNicknameNative;
Java_org_mozilla_jss_CryptoManager_findPrivKeyByCertNative;
Java_org_mozilla_jss_CryptoManager_getCACerts;
Java_org_mozilla_jss_CryptoManager_getPermCerts;
Java_org_mozilla_jss_CryptoManager_importCRLNative;
Java_org_mozilla_jss_CryptoManager_importCertPackageNative;
Java_org_mozilla_jss_CryptoManager_importCertToPermNative;
Java_org_mozilla_jss_CryptoManager_initializeAllNative;
Java_org_mozilla_jss_CryptoManager_putModulesInVector;
Java_org_mozilla_jss_CryptoManager_setNativePasswordCallback;
Java_org_mozilla_jss_pkcs11_CertProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_CipherContextProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_PK11Module_getLibraryName;
Java_org_mozilla_jss_pkcs11_PK11Module_getName;
Java_org_mozilla_jss_pkcs11_PK11Module_putTokensInVector;
Java_org_mozilla_jss_pkcs11_ModuleProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_PK11Cert_getEncoded;
Java_org_mozilla_jss_pkcs11_PK11Cert_getIssuerDNString;
Java_org_mozilla_jss_pkcs11_PK11Cert_getNickname;
Java_org_mozilla_jss_pkcs11_PK11Cert_getOwningToken;
Java_org_mozilla_jss_pkcs11_PK11Cert_getPublicKey;
Java_org_mozilla_jss_pkcs11_PK11Cert_getSerialNumberByteArray;
Java_org_mozilla_jss_pkcs11_PK11Cert_getSubjectDNString;
Java_org_mozilla_jss_pkcs11_PK11Cert_getTrust;
Java_org_mozilla_jss_pkcs11_PK11Cert_getUniqueID;
Java_org_mozilla_jss_pkcs11_PK11Cert_getVersion;
Java_org_mozilla_jss_pkcs11_PK11Cert_setTrust;
Java_org_mozilla_jss_pkcs11_PK11Cipher_finalizeContext;
Java_org_mozilla_jss_pkcs11_PK11Cipher_initContext;
Java_org_mozilla_jss_pkcs11_PK11Cipher_updateContext;
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapPrivWithSym;
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithPriv;
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithSym;
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapPrivWithSym;
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithPub;
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithSym;
Java_org_mozilla_jss_pkcs11_PK11MessageDigest_digest;
Java_org_mozilla_jss_pkcs11_PK11MessageDigest_initDigest;
Java_org_mozilla_jss_pkcs11_PK11MessageDigest_initHMAC;
Java_org_mozilla_jss_pkcs11_PK11MessageDigest_update;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_getKeyType;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_getOwningToken;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_getStrength;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_getUniqueID;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_verifyKeyIsOnToken;
Java_org_mozilla_jss_pkcs11_PK11PubKey_DSAFromRaw;
Java_org_mozilla_jss_pkcs11_PK11PubKey_RSAFromRaw;
Java_org_mozilla_jss_pkcs11_PK11PubKey_getEncoded;
Java_org_mozilla_jss_pkcs11_PK11PubKey_getKeyType;
Java_org_mozilla_jss_pkcs11_PK11PubKey_verifyKeyIsOnToken;
Java_org_mozilla_jss_pkcs11_PK11SymKey_getKeyData;
Java_org_mozilla_jss_pkcs11_PK11SymKey_getKeyType;
Java_org_mozilla_jss_pkcs11_PK11SymKey_getOwningToken;
Java_org_mozilla_jss_pkcs11_PK11SymKey_getStrength;
Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPair;
Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPair;
Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generateNormal;
Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generatePBE;
Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generatePBE_1IV;
Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_nativeClone;
Java_org_mozilla_jss_pkcs11_PrivateKeyProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_PublicKeyProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_SymKeyProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_PK11Token_PWInitable;
Java_org_mozilla_jss_pkcs11_PK11Token_SSOPasswordIsCorrect;
Java_org_mozilla_jss_pkcs11_PK11Token_changePassword;
Java_org_mozilla_jss_pkcs11_PK11Token_doesAlgorithm;
Java_org_mozilla_jss_pkcs11_PK11Token_generatePK10;
Java_org_mozilla_jss_pkcs11_PK11Token_getLoginMode;
Java_org_mozilla_jss_pkcs11_PK11Token_getLoginTimeoutMinutes;
Java_org_mozilla_jss_pkcs11_PK11Token_getName;
Java_org_mozilla_jss_pkcs11_PK11Token_initPassword;
Java_org_mozilla_jss_pkcs11_PK11Token_isLoggedIn;
Java_org_mozilla_jss_pkcs11_PK11Token_isPresent;
Java_org_mozilla_jss_pkcs11_PK11Token_isWritable;
Java_org_mozilla_jss_pkcs11_PK11Token_logout;
Java_org_mozilla_jss_pkcs11_PK11Token_nativeLogin;
Java_org_mozilla_jss_pkcs11_PK11Token_passwordIsInitialized;
Java_org_mozilla_jss_pkcs11_PK11Token_setLoginMode;
Java_org_mozilla_jss_pkcs11_PK11Token_setLoginTimeoutMinutes;
Java_org_mozilla_jss_pkcs11_PK11Token_userPasswordIsCorrect;
Java_org_mozilla_jss_pkcs11_TokenProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_PK11Signature_engineRawSignNative;
Java_org_mozilla_jss_pkcs11_PK11Signature_engineRawVerifyNative;
Java_org_mozilla_jss_pkcs11_PK11Signature_engineSignNative;
Java_org_mozilla_jss_pkcs11_PK11Signature_engineUpdateNative;
Java_org_mozilla_jss_pkcs11_PK11Signature_engineVerifyNative;
Java_org_mozilla_jss_pkcs11_PK11Signature_initSigContext;
Java_org_mozilla_jss_pkcs11_PK11Signature_initVfyContext;
Java_org_mozilla_jss_pkcs11_PK11Store_deleteCert;
Java_org_mozilla_jss_pkcs11_PK11Store_deletePrivateKey;
Java_org_mozilla_jss_pkcs11_PK11Store_importPrivateKey;
Java_org_mozilla_jss_pkcs11_PK11Store_putCertsInVector;
Java_org_mozilla_jss_pkcs11_PK11Store_putKeysInVector;
Java_org_mozilla_jss_pkcs11_SigContextProxy_releaseNativeResources;
Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getModulusByteArray;
Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getPublicExponentByteArray;
Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getGByteArray;
Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getPByteArray;
Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getQByteArray;
Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getYByteArray;
Java_org_mozilla_jss_pkcs11_PK11SecureRandom_nextBytes;
Java_org_mozilla_jss_pkcs11_PK11SecureRandom_setSeed;
Java_org_mozilla_jss_ssl_SSLServerSocket_clearSessionCache;
Java_org_mozilla_jss_ssl_SSLServerSocket_configServerSessionIDCache;
Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCertNickname;
Java_org_mozilla_jss_ssl_SSLServerSocket_socketAccept;
Java_org_mozilla_jss_ssl_SSLServerSocket_socketListen;
Java_org_mozilla_jss_ssl_SSLSocket_forceHandshake;
Java_org_mozilla_jss_ssl_SSLSocket_getKeepAlive;
Java_org_mozilla_jss_ssl_SSLSocket_getLocalAddressNative;
Java_org_mozilla_jss_ssl_SSLSocket_getPort;
Java_org_mozilla_jss_ssl_SSLSocket_getReceiveBufferSize;
Java_org_mozilla_jss_ssl_SSLSocket_getSendBufferSize;
Java_org_mozilla_jss_ssl_SSLSocket_getSoLinger;
Java_org_mozilla_jss_ssl_SSLSocket_getStatus;
Java_org_mozilla_jss_ssl_SSLSocket_getTcpNoDelay;
Java_org_mozilla_jss_ssl_SSLSocket_invalidateSession;
Java_org_mozilla_jss_ssl_SSLSocket_redoHandshake;
Java_org_mozilla_jss_ssl_SSLSocket_resetHandshakeNative;
Java_org_mozilla_jss_ssl_SSLSocket_setCipherPolicyNative;
Java_org_mozilla_jss_ssl_SSLSocket_setCipherPreference;
Java_org_mozilla_jss_ssl_SSLSocket_setKeepAlive;
Java_org_mozilla_jss_ssl_SSLSocket_setReceiveBufferSize;
Java_org_mozilla_jss_ssl_SSLSocket_setSSLDefaultOption;
Java_org_mozilla_jss_ssl_SSLSocket_setSendBufferSize;
Java_org_mozilla_jss_ssl_SSLSocket_setSoLinger;
Java_org_mozilla_jss_ssl_SSLSocket_setTcpNoDelay;
Java_org_mozilla_jss_ssl_SSLSocket_shutdownNative;
Java_org_mozilla_jss_ssl_SSLSocket_socketAvailable;
Java_org_mozilla_jss_ssl_SSLSocket_socketConnect;
Java_org_mozilla_jss_ssl_SSLSocket_socketRead;
Java_org_mozilla_jss_ssl_SSLSocket_socketWrite;
Java_org_mozilla_jss_ssl_SocketBase_getLocalPortNative;
Java_org_mozilla_jss_ssl_SocketBase_getPeerAddressNative;
Java_org_mozilla_jss_ssl_SocketBase_setClientCertNicknameNative;
Java_org_mozilla_jss_ssl_SocketBase_requestClientAuthNoExpiryCheckNative;
Java_org_mozilla_jss_ssl_SocketBase_setSSLOption;
Java_org_mozilla_jss_ssl_SocketBase_socketBind;
Java_org_mozilla_jss_ssl_SocketBase_socketClose;
Java_org_mozilla_jss_ssl_SocketBase_socketCreate;
Java_org_mozilla_jss_util_Debug_setNativeLevel;
Java_org_mozilla_jss_util_Password_readPasswordFromConsole;
;+#
;+# Data objects (NONE)
;+#
;+#
;+# commands (NONE)
;+#
;+#
;+ local:
;+ *;
;+};
;+JSS_3.1 { # JSS 3.1 release
;+ global:
Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymPlaintext;
Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo;
;+ local:
;+ *;
;+};
;+JSS_3.1.1 { # JSS 3.1.1 release
;+ global:
Java_org_mozilla_jss_ssl_SSLServerSocket_setReuseAddress;
Java_org_mozilla_jss_ssl_SSLServerSocket_getReuseAddress;
;+ local:
;+ *;
;+};
;+JSS_3.2 { # JSS 3.2 release
;+ global:
Java_org_mozilla_jss_crypto_SecretDecoderRing_encrypt;
Java_org_mozilla_jss_crypto_SecretDecoderRing_decrypt;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_fromPrivateKeyInfo;
Java_org_mozilla_jss_pkcs11_PK11PubKey_fromRawNative;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getRawAliases;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineDeleteEntry;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getDERCert;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getCertNickname;
Java_org_mozilla_jss_pkcs11_PK11PubKey_fromSPKI;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineGetKey;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineIsCertificateEntry;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineSetKeyEntryNative;
Java_org_mozilla_jss_CryptoManager_initializeAllNative2;
Java_org_mozilla_jss_ssl_SocketBase_getLocalAddressNative;
Java_org_mozilla_jss_pkcs11_PK11PrivKey_getDSAParamsNative;
Java_org_mozilla_jss_CryptoManager_verifyCertNowNative;
Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCert;
Java_org_mozilla_jss_ssl_SocketBase_setClientCert;
Java_org_mozilla_jss_CryptoManager_verifyCertTempNative;
Java_org_mozilla_jss_ssl_SocketProxy_releaseNativeResources;
;+ local:
;+ *;
;+};
;+JSS_3.3 { # JSS 3.3 release
;+ global:
Java_org_mozilla_jss_ssl_SSLSocket_getImplementedCipherSuites;
Java_org_mozilla_jss_ssl_SSLSocket_getCipherPreferenceDefault;
Java_org_mozilla_jss_ssl_SSLSocket_setCipherPreferenceDefault;
Java_org_mozilla_jss_ssl_SSLSocket_getCipherPreference;
Java_org_mozilla_jss_CryptoManager_configureOCSPNative;
Java_org_mozilla_jss_pkcs11_PK11SymKey_getLength;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getCertObject;
Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineGetKeyNative;
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateKeyNative;
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupKeyNative;
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_deleteKeyNative;
;+ local:
;+ *;
;+};
;+JSS_3.4 { # JSS 3.4 release
;+ global:
Java_org_mozilla_jss_pkcs11_PK11Cipher_initContextWithKeyBits;
;+ local:
;+ *;
;+};
;+JSS_3.5 { # JSS 3.5 release
;+ global:
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateUniqueNamedKeyNative;
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupUniqueNamedKeyNative;
;+ local:
;+ *;
;+};

View File

@@ -1,101 +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 Java security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the 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 "jssver.h"
#include <winver.h>
#define MY_LIBNAME "jss"
#define MY_FILEDESCRIPTION "JSS Library"
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define JSS_VMAJOR_STR STRINGIZE2(JSS_VMAJOR)
#ifdef _DEBUG
#define MY_DEBUG_STR " (debug)"
#define MY_FILEFLAGS_1 VS_FF_DEBUG
#else
#define MY_DEBUG_STR ""
#define MY_FILEFLAGS_1 0x0L
#endif
#if JSS_BETA
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
#else
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
#endif
#ifdef WINNT
#define MY_FILEOS VOS_NT_WINDOWS32
#else
#define MY_FILEOS VOS__WINDOWS32
#endif
#define MY_INTERNAL_NAME MY_LIBNAME JSS_VMAJOR_STR
/////////////////////////////////////////////////////////////////////////////
//
// Version-information resource
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION JSS_VMAJOR,JSS_VMINOR,JSS_VPATCH,0
PRODUCTVERSION JSS_VMAJOR,JSS_VMINOR,JSS_VPATCH,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS MY_FILEFLAGS_2
FILEOS MY_FILEOS
FILETYPE VFT_DLL
FILESUBTYPE 0x0L // not used
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0" // Lang=US English, CharSet=Unicode
BEGIN
VALUE "CompanyName", "Netscape Communications Corporation\0"
VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
VALUE "FileVersion", JSS_VERSION "\0"
VALUE "InternalName", MY_INTERNAL_NAME "\0"
VALUE "LegalCopyright", "Copyright \251 1994-2001 Netscape Communications Corporation\0"
VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
VALUE "ProductName", "Network Security Services for Java\0"
VALUE "ProductVersion", JSS_VERSION "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -1,45 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
CORE_DEPTH = ../..
MODULE = jss
NS_USE_JDK = 1
LIBRARY_NAME = jss
LIBRARY_VERSION = 4

View File

@@ -1,54 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
release_md:: release_sanitize
release_sanitize::
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsscrypto$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jssmanage$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsspkcs11$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jsspolicy$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jssssl$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(DLL_PREFIX)jssutil$(DYNAMIC_LIB_EXTENSION)$(DYNAMIC_LIB_SUFFIX)
ifeq ($(OS_ARCH),WINNT)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsscrypto$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jssmanage$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsspkcs11$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jsspolicy$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jssssl$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX)
-rm $(SOURCE_RELEASE_PREFIX)/$(SOURCE_RELEASE_LIB_DIR)/$(IMPORT_LIB_PREFIX)jssutil$(IMPORT_LIB_EXTENSION)$(IMPORT_LIB_SUFFIX)
endif

View File

@@ -1,61 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
CORE_DEPTH = ..
MODULE = jss
#
# Whenever you change the NSPR or NSS version that JSS imports,
# please update the JAR_NSPR_VERSION or JAR_NSS_VERSION value in
# org/mozilla/jss/CryptoManager.java.
#
# To change the JSS version, update the version macros in
# org/mozilla/jss/util/jssver.h, the JAR_JSS_VERSION value in
# org/mozilla/jss/CryptoManager.java, and the PRODUCT_VERSION
# and PRODUCT_NAME values in pkg/solaris/Makefile.com.
#
IMPORTS = nss/NSS_3_9_RTM \
nspr20/v4.4.1 \
$(NULL)
DIRS = org \
lib \
$(NULL)
RELEASE = jss

View File

@@ -1,80 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################

View File

@@ -1,43 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
CORE_DEPTH = ../..
MODULE = jss
DIRS = mozilla \
$(NULL)

View File

@@ -1,80 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################

View File

@@ -1,46 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss;
/**
* Thrown if a CRL cannot be imported
*/
public class CRLImportException extends java.lang.Exception {
public CRLImportException() {}
public CRLImportException(String mesg) {
super(mesg);
}
}

View File

@@ -1,47 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss;
/**
* This exception is thrown if the certificate database does not exist,
* or if an error occurs while opening it.
*/
public class CertDatabaseException extends java.lang.Exception {
public CertDatabaseException() {}
public CertDatabaseException(String mesg) {
super(mesg);
}
}

View File

@@ -1,951 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
#include "_jni/org_mozilla_jss_CryptoManager.h"
#include <secitem.h>
#include <secmod.h>
#include <cert.h>
#include <certt.h>
#include <key.h>
#include <ocsp.h>
#include <pk11func.h>
#include <nspr.h>
#include <plstr.h>
#include <pkcs11.h>
#include <nss.h>
#include <ssl.h>
#include <jssutil.h>
#include <java_ids.h>
#include <jss_exceptions.h>
#include <jssver.h>
#include "pk11util.h"
#if defined(AIX) || defined(HPUX) || defined(LINUX)
#include <signal.h>
#endif
/********************************************************************/
/* The following VERSION Strings should be updated in the following */
/* files everytime a new release of JSS is generated: */
/* */
/* jss.jar: ns/ninja/org/mozilla/jss/manage/CryptoManager.java */
/* jss.dll: ns/ninja/org/mozilla/jss/manage/CryptoManager.c */
/* */
/********************************************************************/
static const char* DLL_JSS_VERSION = "JSS_VERSION = " JSS_VERSION;
static const char* DLL_NSS_VERSION = "NSS_VERSION = " NSS_VERSION;
static const char* DLL_NSPR_VERSION = "NSPR_VERSION = " PR_VERSION;
static jobject
makePWCBInfo(JNIEnv *env, PK11SlotInfo *slot);
static char*
getPWFromCallback(PK11SlotInfo *slot, PRBool retry, void *arg);
/*************************************************************
* AIX, HP, and Linux signal handling madness
*
* In order for the JVM, kernel, and NSPR to work together, we setup
* a signal handler for SIGCHLD that does nothing. This is only done
* on AIX, HP, and Linux.
*************************************************************/
#if defined(AIX) || defined(HPUX) || defined(LINUX)
static PRStatus
handleSigChild(JNIEnv *env) {
struct sigaction action;
sigset_t signalset;
int result;
sigemptyset(&signalset);
action.sa_handler = SIG_DFL;
action.sa_mask = signalset;
action.sa_flags = 0;
result = sigaction( SIGCHLD, &action, NULL );
if( result != 0 ) {
JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION,
"Failed to set SIGCHLD handler");
return PR_FAILURE;
}
return PR_SUCCESS;
}
#endif
int ConfigureOCSP(
JNIEnv *env,
jboolean ocspCheckingEnabled,
jstring ocspResponderURL,
jstring ocspResponderCertNickname )
{
char *ocspResponderURL_string=NULL;
char *ocspResponderCertNickname_string=NULL;
SECStatus status;
int result = SECSuccess;
CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
/* if caller specified default responder, get the
* strings associated with these args
*/
if (ocspResponderURL) {
ocspResponderURL_string =
(char*) (*env)->GetStringUTFChars(env, ocspResponderURL, NULL);
if (ocspResponderURL_string == NULL) {
JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION,
"OCSP invalid URL");
result = SECFailure;
goto loser;
}
}
if (ocspResponderCertNickname) {
ocspResponderCertNickname_string =
(char*) (*env)->GetStringUTFChars(env, ocspResponderCertNickname, NULL);
if (ocspResponderCertNickname_string == NULL) {
JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION,
"OCSP invalid nickname");
result = SECFailure;
goto loser;
}
}
/* first disable OCSP - we'll enable it later */
CERT_DisableOCSPChecking(certdb);
/* if they set the default responder, then set it up
* and enable it
*/
if (ocspResponderURL) {
/* if ocspResponderURL is set they must specify the
ocspResponderCertNickname */
if (ocspResponderCertNickname == NULL ) {
JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION,
"if OCSP responderURL is set, the Responder Cert nickname must be set");
result = SECFailure;
goto loser;
} else {
CERTCertificate *cert;
/* if the nickname is set */
cert = CERT_FindCertByNickname(certdb, ocspResponderCertNickname_string);
if (cert == NULL) {
/*
* look for the cert on an external token.
*/
cert = PK11_FindCertFromNickname(ocspResponderCertNickname_string, NULL);
}
if (cert == NULL) {
JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION,
"Unable to find the OCSP Responder Certificate nickname.");
result = SECFailure;
goto loser;
}
CERT_DestroyCertificate(cert);
}
status =
CERT_SetOCSPDefaultResponder( certdb,
ocspResponderURL_string,
ocspResponderCertNickname_string
);
if (status == SECFailure) {
/* deal with error */
JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION,
"OCSP Could not set responder");
result = SECFailure;
goto loser;
}
CERT_EnableOCSPDefaultResponder(certdb);
}
else {
/* if no defaultresponder is set, disable it */
CERT_DisableOCSPDefaultResponder(certdb);
}
/* enable OCSP checking if requested */
if (ocspCheckingEnabled) {
CERT_EnableOCSPChecking(certdb);
}
loser:
if (ocspResponderURL_string) {
(*env)->ReleaseStringUTFChars(env,
ocspResponderURL, ocspResponderURL_string);
}
if (ocspResponderCertNickname_string) {
(*env)->ReleaseStringUTFChars(env,
ocspResponderCertNickname, ocspResponderCertNickname_string);
}
return result;
}
/**********************************************************************
* This is the PasswordCallback object that will be used to login
* to tokens implicitly.
*/
static jobject globalPasswordCallback = NULL;
/**********************************************************************
* The Java virtual machine can be used to retrieve the JNI environment
* pointer from callback functions.
*/
JavaVM * JSS_javaVM;
JNIEXPORT void JNICALL
Java_org_mozilla_jss_CryptoManager_initializeAllNative
(JNIEnv *env, jclass clazz,
jstring configDir,
jstring certPrefix,
jstring keyPrefix,
jstring secmodName,
jboolean readOnly,
jstring manuString,
jstring libraryString,
jstring tokString,
jstring keyTokString,
jstring slotString,
jstring keySlotString,
jstring fipsString,
jstring fipsKeyString,
jboolean ocspCheckingEnabled,
jstring ocspResponderURL,
jstring ocspResponderCertNickname )
{
Java_org_mozilla_jss_CryptoManager_initializeAllNative2(
env,
clazz,
configDir,
certPrefix,
keyPrefix,
secmodName,
readOnly,
manuString,
libraryString,
tokString,
keyTokString,
slotString,
keySlotString,
fipsString,
fipsKeyString,
ocspCheckingEnabled,
ocspResponderURL,
ocspResponderCertNickname,
JNI_FALSE /*initializeJavaOnly*/ );
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_CryptoManager_initializeAllNative2
(JNIEnv *env, jclass clazz,
jstring configDir,
jstring certPrefix,
jstring keyPrefix,
jstring secmodName,
jboolean readOnly,
jstring manuString,
jstring libraryString,
jstring tokString,
jstring keyTokString,
jstring slotString,
jstring keySlotString,
jstring fipsString,
jstring fipsKeyString,
jboolean ocspCheckingEnabled,
jstring ocspResponderURL,
jstring ocspResponderCertNickname,
jboolean initializeJavaOnly )
{
SECStatus rv = SECFailure;
JavaVM *VMs[5];
jint numVMs;
char *szConfigDir = NULL;
char *szCertPrefix = NULL;
char *szKeyPrefix = NULL;
char *szSecmodName = NULL;
char *manuChars=NULL;
char *libraryChars=NULL;
char *tokChars=NULL;
char *keyTokChars=NULL;
char *slotChars=NULL;
char *keySlotChars=NULL;
char *fipsChars=NULL;
char *fipsKeyChars=NULL;
PRUint32 initFlags;
/* This is thread-safe because initialize is synchronized */
static PRBool initialized=PR_FALSE;
if( configDir == NULL ||
manuString == NULL ||
libraryString == NULL ||
tokString == NULL ||
keyTokString == NULL ||
slotString == NULL ||
keySlotString == NULL ||
fipsString == NULL ||
fipsKeyString == NULL )
{
JSS_throw(env, NULL_POINTER_EXCEPTION);
goto finish;
}
/* Make sure initialize() completes only once */
if(initialized) {
JSS_throw(env, ALREADY_INITIALIZED_EXCEPTION);
goto finish;
}
/*
* Save the JavaVM pointer so we can retrieve the JNI environment
* later. This only works if there is only one Java VM.
*/
if( (*env)->GetJavaVM(env, &JSS_javaVM) != 0 ) {
JSS_trace(env, JSS_TRACE_ERROR,
"Unable to to access Java virtual machine");
PR_ASSERT(PR_FALSE);
goto finish;
}
/*
* Initialize the errcode translation table.
*/
JSS_initErrcodeTranslationTable();
/*
* The rest of the initialization (the NSS stuff) is skipped if
* the initializeJavaOnly flag is set.
*/
if( initializeJavaOnly) {
initialized = PR_TRUE;
goto finish;
}
/*
* Set the PKCS #11 strings
*/
manuChars = (char*) (*env)->GetStringUTFChars(env, manuString, NULL);
libraryChars = (char*) (*env)->GetStringUTFChars(env, libraryString, NULL);
tokChars = (char*) (*env)->GetStringUTFChars(env, tokString, NULL);
keyTokChars = (char*) (*env)->GetStringUTFChars(env, keyTokString, NULL);
slotChars = (char*) (*env)->GetStringUTFChars(env, slotString, NULL);
keySlotChars = (char*) (*env)->GetStringUTFChars(env, keySlotString, NULL);
fipsChars = (char*) (*env)->GetStringUTFChars(env, fipsString, NULL);
fipsKeyChars = (char*) (*env)->GetStringUTFChars(env, fipsKeyString, NULL);
if( (*env)->ExceptionOccurred(env) ) {
ASSERT_OUTOFMEM(env);
goto finish;
}
PR_ASSERT( strlen(manuChars) == 33 );
PR_ASSERT( strlen(libraryChars) == 33 );
PR_ASSERT( strlen(tokChars) == 33 );
PR_ASSERT( strlen(keyTokChars) == 33 );
PR_ASSERT( strlen(slotChars) == 65 );
PR_ASSERT( strlen(keySlotChars) == 65 );
PR_ASSERT( strlen(fipsChars) == 65 );
PR_ASSERT( strlen(fipsKeyChars) == 65 );
PK11_ConfigurePKCS11( manuChars,
libraryChars,
tokChars,
keyTokChars,
slotChars,
keySlotChars,
fipsChars,
fipsKeyChars,
0, /* minimum pin length */
PR_FALSE /* password required */
);
szConfigDir = (char*) (*env)->GetStringUTFChars(env, configDir, NULL);
if( certPrefix != NULL && keyPrefix != NULL && secmodName != NULL ) {
/*
* Set up arguments to NSS_Initialize
*/
szCertPrefix = (char*) (*env)->GetStringUTFChars(env, certPrefix, NULL);
szKeyPrefix = (char*) (*env)->GetStringUTFChars(env, keyPrefix, NULL);
szSecmodName = (char*) (*env)->GetStringUTFChars(env, secmodName, NULL);
initFlags = 0;
if( readOnly ) {
initFlags |= NSS_INIT_READONLY;
}
/*
* Initialize NSS.
*/
rv = NSS_Initialize(szConfigDir, szCertPrefix, szKeyPrefix,
szSecmodName, initFlags);
} else {
if( readOnly ) {
rv = NSS_Init(szConfigDir);
} else {
rv = NSS_InitReadWrite(szConfigDir);
}
}
if( rv != SECSuccess ) {
JSS_throwMsg(env, SECURITY_EXCEPTION,
"Unable to initialize security library");
goto finish;
}
/*
* Set default password callback. This is the only place this
* should ever be called if you are using Ninja.
*/
PK11_SetPasswordFunc(getPWFromCallback);
/*
* Setup NSS to call the specified OCSP responder
*/
rv = ConfigureOCSP(
env,
ocspCheckingEnabled,
ocspResponderURL,
ocspResponderCertNickname );
if (rv != SECSuccess) {
goto finish;
}
/*
* Set up policy. We're always domestic now. Thanks to the US Government!
*/
if( NSS_SetDomesticPolicy() != SECSuccess ) {
JSS_throwMsg(env, SECURITY_EXCEPTION, "Unable to set security policy");
goto finish;
}
initialized = PR_TRUE;
finish:
/* LET'S BE CAREFUL. Unbraced if statements ahead. */
if(szConfigDir)
(*env)->ReleaseStringUTFChars(env, configDir, szConfigDir);
if(szCertPrefix)
(*env)->ReleaseStringUTFChars(env, certPrefix, szCertPrefix);
if(szKeyPrefix)
(*env)->ReleaseStringUTFChars(env, keyPrefix, szKeyPrefix);
if(szSecmodName)
(*env)->ReleaseStringUTFChars(env, secmodName, szSecmodName);
if(manuChars)
(*env)->ReleaseStringUTFChars(env, manuString, manuChars);
if(libraryChars)
(*env)->ReleaseStringUTFChars(env, libraryString, libraryChars);
if(tokChars)
(*env)->ReleaseStringUTFChars(env, tokString, tokChars);
if(keyTokChars)
(*env)->ReleaseStringUTFChars(env, keyTokString, keyTokChars);
if(slotChars)
(*env)->ReleaseStringUTFChars(env, slotString, slotChars);
if(keySlotChars)
(*env)->ReleaseStringUTFChars(env, keySlotString, keySlotChars);
if(fipsChars)
(*env)->ReleaseStringUTFChars(env, fipsString, fipsChars);
if(fipsKeyChars)
(*env)->ReleaseStringUTFChars(env, fipsKeyString, fipsKeyChars);
return;
}
/**********************************************************************
*
* JSS_setPasswordCallback
*
* Sets the global PasswordCallback object, which will be used to
* login to tokens implicitly if necessary.
*
*/
void
JSS_setPasswordCallback(JNIEnv *env, jobject callback)
{
PR_ASSERT(env!=NULL && callback!=NULL);
/* Free the previously-registered password callback */
if( globalPasswordCallback != NULL ) {
(*env)->DeleteGlobalRef(env, globalPasswordCallback);
globalPasswordCallback = NULL;
}
/* Store the new password callback */
globalPasswordCallback = (*env)->NewGlobalRef(env, callback);
if(globalPasswordCallback == NULL) {
JSS_throw(env, OUT_OF_MEMORY_ERROR);
}
}
/**********************************************************************
*
* CryptoManager.setNativePasswordCallback
*
* Sets the global PasswordCallback object, which will be used to
* login to tokens implicitly if necessary.
*
*/
JNIEXPORT void JNICALL
Java_org_mozilla_jss_CryptoManager_setNativePasswordCallback
(JNIEnv *env, jclass clazz, jobject callback)
{
JSS_setPasswordCallback(env, callback);
}
/********************************************************************
*
* g e t P W F r o m C a l l b a c k
*
* Extracts a password from a password callback and returns
* it to PKCS #11.
*
* INPUTS
* slot
* The PK11SlotInfo* for the slot we are logging into.
* retry
* PR_TRUE if this is the first time we are trying to login,
* PR_FALSE if we tried before and our password was wrong.
* arg
* This can contain a Java PasswordCallback object reference,
* or NULL to use the default password callback.
* RETURNS
* The password as extracted from the callback, or NULL if the
* callback gives up.
*/
static char*
getPWFromCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
{
jobject pwcbInfo;
jobject pwObject;
jbyteArray pwArray=NULL;
char* pwchars;
char* returnchars=NULL;
jclass callbackClass;
jclass passwordClass;
jmethodID getPWMethod;
jmethodID getByteCopyMethod;
jmethodID clearMethod;
jthrowable exception;
jobject callback;
JNIEnv *env;
PR_ASSERT(slot!=NULL);
if(slot==NULL) {
return NULL;
}
/* Get the callback from the arg, or use the default */
PR_ASSERT(sizeof(void*) == sizeof(jobject));
callback = (jobject)arg;
if(callback == NULL) {
callback = globalPasswordCallback;
if(callback == NULL) {
/* No global password callback set, no way to get a password */
return NULL;
}
}
/* Get the JNI environment */
if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){
PR_ASSERT(PR_FALSE);
goto finish;
}
PR_ASSERT(env != NULL);
/*****************************************
* Construct the JSS_PasswordCallbackInfo
*****************************************/
pwcbInfo = makePWCBInfo(env, slot);
if(pwcbInfo==NULL) {
goto finish;
}
/*****************************************
* Get the callback class and methods
*****************************************/
callbackClass = (*env)->GetObjectClass(env, callback);
if(callbackClass == NULL) {
JSS_trace(env, JSS_TRACE_ERROR, "Failed to find password "
"callback class");
PR_ASSERT(PR_FALSE);
}
if(retry) {
getPWMethod = (*env)->GetMethodID(
env,
callbackClass,
PW_CALLBACK_GET_PW_AGAIN_NAME,
PW_CALLBACK_GET_PW_AGAIN_SIG);
} else {
getPWMethod = (*env)->GetMethodID(
env,
callbackClass,
PW_CALLBACK_GET_PW_FIRST_NAME,
PW_CALLBACK_GET_PW_FIRST_SIG);
}
if(getPWMethod == NULL) {
JSS_trace(env, JSS_TRACE_ERROR,
"Failed to find password callback accessor method");
ASSERT_OUTOFMEM(env);
goto finish;
}
/*****************************************
* Get the password from the callback
*****************************************/
pwObject = (*env)->CallObjectMethod(
env,
callback,
getPWMethod,
pwcbInfo);
if( (*env)->ExceptionOccurred(env) != NULL) {
goto finish;
}
if( pwObject == NULL ) {
JSS_throw(env, GIVE_UP_EXCEPTION);
goto finish;
}
/*****************************************
* Get Password class and methods
*****************************************/
passwordClass = (*env)->GetObjectClass(env, pwObject);
if(passwordClass == NULL) {
JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password class");
ASSERT_OUTOFMEM(env);
goto finish;
}
getByteCopyMethod = (*env)->GetMethodID(
env,
passwordClass,
PW_GET_BYTE_COPY_NAME,
PW_GET_BYTE_COPY_SIG);
clearMethod = (*env)->GetMethodID( env,
passwordClass,
PW_CLEAR_NAME,
PW_CLEAR_SIG);
if(getByteCopyMethod==NULL || clearMethod==NULL) {
JSS_trace(env, JSS_TRACE_ERROR,
"Failed to find Password manipulation methods from native "
"implementation");
ASSERT_OUTOFMEM(env);
goto finish;
}
/************************************************
* Get the bytes from the password, then clear it
***********************************************/
pwArray = (*env)->CallObjectMethod( env, pwObject, getByteCopyMethod);
(*env)->CallVoidMethod(env, pwObject, clearMethod);
exception = (*env)->ExceptionOccurred(env);
if(exception == NULL) {
PR_ASSERT(pwArray != NULL);
/*************************************************************
* Copy the characters out of the byte array,
* then erase it
*************************************************************/
pwchars = (char*) (*env)->GetByteArrayElements(env, pwArray, NULL);
PR_ASSERT(pwchars!=NULL);
returnchars = PL_strdup(pwchars);
JSS_wipeCharArray(pwchars);
(*env)->ReleaseByteArrayElements(env, pwArray, (jbyte*)pwchars, 0);
} else {
returnchars = NULL;
}
finish:
if( (exception=(*env)->ExceptionOccurred(env)) != NULL) {
#ifdef DEBUG
jclass giveupClass;
jmethodID printStackTrace;
jclass excepClass;
#endif
(*env)->ExceptionClear(env);
#ifdef DEBUG
giveupClass = (*env)->FindClass(env, GIVE_UP_EXCEPTION);
PR_ASSERT(giveupClass != NULL);
if( ! (*env)->IsInstanceOf(env, exception, giveupClass) ) {
excepClass = (*env)->GetObjectClass(env, exception);
printStackTrace = (*env)->GetMethodID(env, excepClass,
"printStackTrace", "()V");
(*env)->CallVoidMethod(env, exception, printStackTrace);
PR_ASSERT( PR_FALSE );
}
PR_ASSERT(returnchars==NULL);
#endif
}
return returnchars;
}
/**********************************************************************
*
* m a k e P W C B I n f o
*
* Creates a Java PasswordCallbackInfo structure from a PKCS #11 token.
* Returns this object, or NULL if an exception was thrown.
*/
static jobject
makePWCBInfo(JNIEnv *env, PK11SlotInfo *slot)
{
jclass infoClass;
jmethodID constructor;
jstring name;
jobject pwcbInfo=NULL;
PR_ASSERT(env!=NULL && slot!=NULL);
/*****************************************
* Turn the token name into a Java String
*****************************************/
name = (*env)->NewStringUTF(env, PK11_GetTokenName(slot));
if(name == NULL) {
ASSERT_OUTOFMEM(env);
goto finish;
}
/*****************************************
* Look up the class and constructor
*****************************************/
infoClass = (*env)->FindClass(env, TOKEN_CBINFO_CLASS_NAME);
if(infoClass == NULL) {
JSS_trace(env, JSS_TRACE_ERROR, "Unable to find TokenCallbackInfo "
"class");
ASSERT_OUTOFMEM(env);
goto finish;
}
constructor = (*env)->GetMethodID( env,
infoClass,
TOKEN_CBINFO_CONSTRUCTOR_NAME,
TOKEN_CBINFO_CONSTRUCTOR_SIG);
if(constructor == NULL) {
JSS_trace(env, JSS_TRACE_ERROR, "Unable to find "
"TokenCallbackInfo constructor");
ASSERT_OUTOFMEM(env);
goto finish;
}
/*****************************************
* Create the CallbackInfo object
*****************************************/
pwcbInfo = (*env)->NewObject(env, infoClass, constructor, name);
if(pwcbInfo == NULL) {
JSS_trace(env, JSS_TRACE_ERROR, "Unable to create TokenCallbackInfo");
ASSERT_OUTOFMEM(env);
}
finish:
return pwcbInfo;
}
/**********************************************************************
* CryptoManager.putModulesInVector
*
* Wraps all PKCS #11 modules in PK11Module Java objects, then puts
* these into a Vector.
*/
JNIEXPORT void JNICALL
Java_org_mozilla_jss_CryptoManager_putModulesInVector
(JNIEnv *env, jobject this, jobject vector)
{
SECMODListLock *listLock=NULL;
SECMODModuleList *list;
SECMODModule *modp=NULL;
jclass vectorClass;
jmethodID addElement;
jobject module;
PR_ASSERT(env!=NULL && this!=NULL && vector!=NULL);
/***************************************************
* Get JNI ids
***************************************************/
vectorClass = (*env)->GetObjectClass(env, vector);
if(vectorClass == NULL) goto finish;
addElement = (*env)->GetMethodID(env,
vectorClass,
VECTOR_ADD_ELEMENT_NAME,
VECTOR_ADD_ELEMENT_SIG);
if(addElement==NULL) goto finish;
/***************************************************
* Lock the list
***************************************************/
listLock = SECMOD_GetDefaultModuleListLock();
PR_ASSERT(listLock!=NULL);
SECMOD_GetReadLock(listLock);
/***************************************************
* Loop over the modules, adding each one to the vector
***************************************************/
for( list = SECMOD_GetDefaultModuleList(); list != NULL; list=list->next) {
PR_ASSERT(list->module != NULL);
/** Make a PK11Module **/
modp = SECMOD_ReferenceModule(list->module);
module = JSS_PK11_wrapPK11Module(env, &modp);
PR_ASSERT(modp==NULL);
if(module == NULL) {
goto finish;
}
/** Stick the PK11Module in the Vector **/
(*env)->CallVoidMethod(env, vector, addElement, module);
}
finish:
/*** Unlock the list ***/
if(listLock != NULL) {
SECMOD_ReleaseReadLock(listLock);
}
/*** Free this module if it wasn't properly Java-ized ***/
if(modp!=NULL) {
SECMOD_DestroyModule(modp);
}
return;
}
/**********************************************************************
* CryptoManager.enableFIPS
*
* Enables or disables FIPS mode.
* INPUTS
* fips
* true means turn on FIPS mode, false means turn it off.
* RETURNS
* true if a switch happened, false if the library was already
* in the requested mode.
* THROWS
* java.security.GeneralSecurityException if an error occurred with
* the PKCS #11 library.
*/
JNIEXPORT jboolean JNICALL
Java_org_mozilla_jss_CryptoManager_enableFIPS
(JNIEnv *env, jclass clazz, jboolean fips)
{
char *name=NULL;
jboolean switched = JNI_FALSE;
SECStatus status;
if( ((fips==JNI_TRUE) && !PK11_IsFIPS()) ||
((fips==JNI_FALSE) && PK11_IsFIPS()) )
{
name = PL_strdup(SECMOD_GetInternalModule()->commonName);
status = SECMOD_DeleteInternalModule(name);
PR_Free(name);
switched = JNI_TRUE;
}
if(status != SECSuccess) {
JSS_throwMsg(env,
GENERAL_SECURITY_EXCEPTION,
"Failed to toggle FIPS mode");
}
return switched;
}
/***********************************************************************
* CryptoManager.FIPSEnabled
*
* Returns true if FIPS mode is currently on, false if it ain't.
*/
JNIEXPORT jboolean JNICALL
Java_org_mozilla_jss_CryptoManager_FIPSEnabled(JNIEnv *env, jobject this)
{
if( PK11_IsFIPS() ) {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
}
/***********************************************************************
* DatabaseCloser.closeDatabases
*
* Closes the cert and key database, rendering the security library
* unusable.
*/
JNIEXPORT void JNICALL
Java_org_mozilla_jss_DatabaseCloser_closeDatabases
(JNIEnv *env, jobject this)
{
NSS_Shutdown();
}
/**********************************************************************
* configureOCSPNative
*
* Allows configuration of the OCSP responder during runtime.
*/
JNIEXPORT void JNICALL
Java_org_mozilla_jss_CryptoManager_configureOCSPNative(
JNIEnv *env, jobject this,
jboolean ocspCheckingEnabled,
jstring ocspResponderURL,
jstring ocspResponderCertNickname )
{
SECStatus rv = SECFailure;
rv = ConfigureOCSP(env,ocspCheckingEnabled,
ocspResponderURL, ocspResponderCertNickname);
if (rv != SECSuccess) {
JSS_throwMsgPrErr(env,
GENERAL_SECURITY_EXCEPTION,
"Failed to configure OCSP");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,77 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss;
/**
* A class for closing databases. Since closing the databases is
* very dangerous and breaks the JSS model, it may only be done from
* special applications. This class should be subclasses by
* authorized subclasses. It cannot be instantiated itself.
*/
public abstract class DatabaseCloser {
private static final String authorizedClosers[] =
{ "org.mozilla.certsetup.apps.CertSetup$DatabaseCloser",
"org.mozilla.jss.CloseDBs" };
/**
* Creates a new DatabaseCloser. This should only be called
* from an authorized subclass. This class cannot itself be
* instantiated.
*
* @throws Exception If the instantiation is not a valid subclass.
*/
public DatabaseCloser() throws Exception {
Class clazz = this.getClass();
String name = clazz.getName();
boolean approved = false;
for(int i=0; i < authorizedClosers.length; i++) {
if( name.equals( authorizedClosers[i] ) ) {
approved = true;
break;
}
}
if(!approved) {
throw new Exception();
}
}
/**
* Closes the certificate and key databases. This is extremely
* dangerous.
*/
protected native void closeDatabases();
}

View File

@@ -1,208 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss;
public final class JSSProvider extends java.security.Provider {
public JSSProvider() {
super("Mozilla-JSS", 3.3,
"Provides Signature, Message Digesting, and RNG");
/////////////////////////////////////////////////////////////
// Signature
/////////////////////////////////////////////////////////////
put("Signature.SHA1withDSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$DSA");
put("Alg.Alias.Signature.DSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSS", "SHA1withDSA");
put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
put("Signature.MD5/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$MD5RSA");
put("Alg.Alias.Signature.MD5withRSA", "MD5/RSA");
put("Signature.MD2/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$MD2RSA");
put("Signature.SHA-1/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA1RSA");
put("Alg.Alias.Signature.SHA1/RSA", "SHA-1/RSA");
put("Alg.Alias.Signature.SHA1withRSA", "SHA-1/RSA");
put("Signature.SHA-256/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256RSA");
put("Alg.Alias.Signature.SHA256/RSA", "SHA-256/RSA");
put("Alg.Alias.Signature.SHA256withRSA", "SHA-256/RSA");
put("Signature.SHA-384/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384RSA");
put("Alg.Alias.Signature.SHA384/RSA", "SHA-384/RSA");
put("Alg.Alias.Signature.SHA384withRSA", "SHA-384/RSA");
put("Signature.SHA-512/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512RSA");
put("Alg.Alias.Signature.SHA512/RSA", "SHA-512/RSA");
put("Alg.Alias.Signature.SHA512withRSA", "SHA-512/RSA");
/////////////////////////////////////////////////////////////
// Message Digesting
/////////////////////////////////////////////////////////////
put("MessageDigest.SHA-1",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA1");
put("MessageDigest.MD2",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$MD2");
put("MessageDigest.MD5",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$MD5");
put("MessageDigest.SHA-256",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA256");
put("MessageDigest.SHA-384",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA384");
put("MessageDigest.SHA-512",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA512");
put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
put("Alg.Alias.MessageDigest.SHA", "SHA-1");
put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
/////////////////////////////////////////////////////////////
// SecureRandom
/////////////////////////////////////////////////////////////
put("SecureRandom.pkcs11prng",
"org.mozilla.jss.provider.java.security.JSSSecureRandomSpi");
/////////////////////////////////////////////////////////////
// KeyPairGenerator
/////////////////////////////////////////////////////////////
put("KeyPairGenerator.RSA",
"org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$RSA");
put("KeyPairGenerator.DSA",
"org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$DSA");
/////////////////////////////////////////////////////////////
// KeyFactory
/////////////////////////////////////////////////////////////
put("KeyFactory.RSA",
"org.mozilla.jss.provider.java.security.KeyFactorySpi1_2");
put("KeyFactory.DSA",
"org.mozilla.jss.provider.java.security.KeyFactorySpi1_2");
/////////////////////////////////////////////////////////////
// AlgorithmParameters
/////////////////////////////////////////////////////////////
put("AlgorithmParameters.IvAlgorithmParameters",
"org.mozilla.jss.provider.java.security.IvAlgorithmParameters");
/////////////////////////////////////////////////////////////
// Cipher
/////////////////////////////////////////////////////////////
put("Cipher.DES",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$DES");
put("Cipher.DESede",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$DESede");
put("Alg.Alias.Cipher.DES3", "DESede");
put("Cipher.AES",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$AES");
put("Cipher.RC4",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RC4");
put("Cipher.RSA",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RSA");
put("Cipher.RC2",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RC2");
/////////////////////////////////////////////////////////////
// KeyGenerator
/////////////////////////////////////////////////////////////
put("KeyGenerator.DES",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$DES");
put("KeyGenerator.DESede",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$DESede");
put("Alg.Alias.KeyGenerator.DES3", "DESede");
put("KeyGenerator.AES",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$AES");
put("KeyGenerator.RC4",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$RC4");
put("KeyGenerator.RC2",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$RC2");
put("KeyGenerator.HmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$HmacSHA1");
put("KeyGenerator.PBAHmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi$PBAHmacSHA1");
/////////////////////////////////////////////////////////////
// SecretKeyFactory
/////////////////////////////////////////////////////////////
put("SecretKeyFactory.DES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$DES");
put("SecretKeyFactory.DESede",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$DESede");
put("Alg.Alias.SecretKeyFactory.DES3", "DESede");
put("SecretKeyFactory.AES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$AES");
put("SecretKeyFactory.RC4",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$RC4");
put("SecretKeyFactory.RC2",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$RC2");
put("SecretKeyFactory.HmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA1");
put("SecretKeyFactory.PBAHmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBAHmacSHA1");
put("SecretKeyFactory.PBEWithMD5AndDES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_MD5_DES_CBC");
put("SecretKeyFactory.PBEWithSHA1AndDES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_DES_CBC");
put("SecretKeyFactory.PBEWithSHA1AndDESede",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_DES3_CBC");
put("Alg.Alias.SecretKeyFactory.PBEWithSHA1AndDES3", "PBEWithSHA1AndDESede");
put("SecretKeyFactory.PBEWithSHA1And128RC4",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_RC4_128");
/////////////////////////////////////////////////////////////
// MAC
/////////////////////////////////////////////////////////////
put("Mac.HmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA1");
put("Alg.Alias.Mac.Hmac-SHA1", "HmacSHA1");
}
}

View File

@@ -1,47 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss;
/**
* This exception is thrown if the key database does not exist, or if
* an error occurs while opening it.
*/
public class KeyDatabaseException extends java.lang.Exception {
public KeyDatabaseException() {}
public KeyDatabaseException(String mesg) {
super(mesg);
}
}

View File

@@ -1,81 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
include rules.mk

View File

@@ -1,46 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss;
/**
* Thrown if a token cannot be found.
*/
public class NoSuchTokenException extends java.lang.Exception {
public NoSuchTokenException() {}
public NoSuchTokenException(String mesg) {
super(mesg);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,131 +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 Network Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.SecretDecoderRing;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.mozilla.jss.asn1.*;
import org.mozilla.jss.pkix.primitive.*;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.TokenException;
import java.io.*;
/**
* Decrypts data with the SecretDecoderRing.
*/
public class Decryptor {
private CryptoToken token;
private KeyManager keyManager;
/**
* Creates a Decryptor for use with the given CryptoToken.
*/
public Decryptor(CryptoToken token) {
this.token = token;
this.keyManager = new KeyManager(token);
}
/**
* Decrypts the given ciphertext. It must have been created previously
* with the SecretDecoderRing, either the JSS version or the NSS version.
* The key used for decryption must exist on the token that was passed
* into the constructor. The token will be searched for a key whose keyID
* matches the keyID in the encoded SecretDecoderRing result.
*
* @param ciphertext A DER-encoded Encoding object, created from a previous
* call to Encryptor.encrypt(), or with the NSS SecretDecoderRing.
* @return The decrypted plaintext.
* @throws InvalidKeyException If no key can be found with the matching
* keyID.
*/
public byte[] decrypt(byte[] ciphertext)
throws CryptoManager.NotInitializedException,
GeneralSecurityException, TokenException
{
CryptoManager cm = CryptoManager.getInstance();
CryptoToken savedToken = cm.getThreadToken();
try {
cm.setThreadToken(token);
//
// decode ASN1
//
Encoding encoding = (Encoding)
ASN1Util.decode(Encoding.getTemplate(), ciphertext);
//
// lookup the algorithm
//
EncryptionAlgorithm alg = EncryptionAlgorithm.fromOID(
encoding.getEncryptionOID() );
//
// Lookup the key
//
SecretKey key = keyManager.lookupKey(alg, encoding.getKeyID());
if( key == null ) {
throw new InvalidKeyException("No matching key found");
}
//
// do the decryption
//
IvParameterSpec ivSpec = new IvParameterSpec(encoding.getIv());
Cipher cipher = Cipher.getInstance(alg.toString(),
Encryptor.PROVIDER);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] paddedPtext = cipher.doFinal(encoding.getCiphertext());
return org.mozilla.jss.crypto.Cipher.unPad(paddedPtext,
alg.getBlockSize() );
} catch(InvalidBERException ibe) {
throw new GeneralSecurityException(ibe.toString());
} catch(IllegalStateException ise) {
throw new GeneralSecurityException(ise.toString());
} catch(org.mozilla.jss.crypto.BadPaddingException bpe) {
throw new javax.crypto.BadPaddingException(bpe.getMessage());
} finally {
cm.setThreadToken(savedToken);
}
}
}

View File

@@ -1,159 +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 Network Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.SecretDecoderRing;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.mozilla.jss.asn1.*;
import org.mozilla.jss.pkix.primitive.*;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import java.io.*;
/**
* An ASN.1 class for encoding the SecretDecoderRing result.
* This class is used internally by the SecretDecoderRing.
* You need not use this class directly in order to use the SecretDecoderRing.
*/
public class Encoding implements ASN1Value {
private SEQUENCE seq = new SEQUENCE();
private byte[] iv;
private OBJECT_IDENTIFIER encOID;
private byte[] ctext;
private byte[] keyID;
public Encoding(byte[] keyID, byte[] iv, OBJECT_IDENTIFIER encOID,
byte[] ctext)
{
this.keyID = keyID;
this.iv = iv;
this.encOID = encOID;
this.ctext = ctext;
AlgorithmIdentifier algID = new AlgorithmIdentifier(
encOID, new OCTET_STRING(iv) );
seq.addElement(new OCTET_STRING(keyID));
seq.addElement(algID);
seq.addElement(new OCTET_STRING(ctext));
}
public byte[] getKeyID() {
return keyID;
}
public byte[] getIv() {
return iv;
}
public OBJECT_IDENTIFIER getEncryptionOID() {
return encOID;
}
public byte[] getCiphertext() {
return ctext;
}
public static final Tag TAG = SEQUENCE.TAG;
public Tag getTag() {
return TAG;
}
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
seq.encode(implicitTag, ostream);
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
/**
* An ASN.1 class for decoding the SecretDecoderRing result.
* This class is used internally by the SecretDecoderRing.
* You need not use this class directly in order to use the
* SecretDecoderRing.
*/
public static class Template extends SEQUENCE.Template {
private SEQUENCE.Template template;
public Template() {
template = new SEQUENCE.Template();
template.addElement(OCTET_STRING.getTemplate() );
template.addElement(AlgorithmIdentifier.getTemplate() );
template.addElement(OCTET_STRING.getTemplate() );
}
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(TAG, istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
SEQUENCE seq = (SEQUENCE) template.decode(implicitTag, istream);
OCTET_STRING keyID = (OCTET_STRING) seq.elementAt(0);
AlgorithmIdentifier algID = (AlgorithmIdentifier)
seq.elementAt(1);
OCTET_STRING ivOS = (OCTET_STRING)
((ANY)algID.getParameters()).decodeWith(
OCTET_STRING.getTemplate());
OCTET_STRING ctextOS = (OCTET_STRING)seq.elementAt(2);
return new Encoding(keyID.toByteArray(),
ivOS.toByteArray(), algID.getOID(),
ctextOS.toByteArray());
}
}
}

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 Network Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.SecretDecoderRing;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.mozilla.jss.asn1.*;
import org.mozilla.jss.pkix.primitive.*;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.TokenException;
import java.io.*;
/**
* Encrypts data with the SecretDecoderRing.
*/
public class Encryptor {
private CryptoToken token;
private byte[] keyID;
private SecretKey key;
private EncryptionAlgorithm alg;
private KeyManager keyManager;
/**
* The default encryption algorithm, currently DES3_CBC.
*/
public static final EncryptionAlgorithm DEFAULT_ENCRYPTION_ALG
= EncryptionAlgorithm.DES3_CBC;
static final String PROVIDER = "Mozilla-JSS";
static final String RNG_ALG = "pkcs11prng";
/**
* Creates an Encryptor on the given CryptoToken, using the key with
* the given keyID and algorithm
* @param token The CryptoToken to use for encryption. The key must
* reside on this token.
* @param keyID The keyID of the key to use for encryption. This key
* must have been generated on this token with KeyManager.
* @param alg The EncryptionAlgorithm this key will be used for.
* @throws InvalidKeyException If no key exists on this token with this
* keyID.
*/
public Encryptor(CryptoToken token, byte[] keyID, EncryptionAlgorithm alg)
throws TokenException, InvalidKeyException
{
this.token = token;
this.keyID = keyID;
this.alg = alg;
this.keyManager = new KeyManager(token);
// make sure this key exists on the token
key = keyManager.lookupKey(alg, keyID);
if( key == null ) {
throw new InvalidKeyException("Key not found");
}
// make sure key matches algorithm
// !!! not sure how to do this
}
/**
* Encrypts a byte array.
* @param plaintext The plaintext bytes to be encrypted.
* @return The ciphertext. This is actually a DER-encoded Encoding
* object. It contains the keyID, AlgorithmIdentifier, and the encrypted
* plaintext. It is compatible with the SDRResult created by NSS's
* SecretDecoderRing.
*/
public byte[] encrypt(byte[] plaintext) throws
CryptoManager.NotInitializedException,
GeneralSecurityException,
InvalidBERException
{
CryptoManager cm = CryptoManager.getInstance();
CryptoToken savedToken = cm.getThreadToken();
try {
cm.setThreadToken(token);
//
// generate an IV
//
byte[] iv = new byte[alg.getIVLength()];
SecureRandom rng = SecureRandom.getInstance(RNG_ALG,
PROVIDER);
rng.nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
//
// do the encryption
//
Cipher cipher = Cipher.getInstance(alg.toString(),PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] paddedPtext =
org.mozilla.jss.crypto.Cipher.pad(
plaintext, alg.getBlockSize() );
byte[] rawCtext = cipher.doFinal(paddedPtext);
//
// package the encrypted content and IV
//
Encoding encoding =
new Encoding(keyID, iv, alg.toOID(), rawCtext);
return ASN1Util.encode(encoding);
} catch(IllegalStateException ise ) {
throw new GeneralSecurityException(ise.toString());
} finally {
cm.setThreadToken(savedToken);
}
}
}

View File

@@ -1,390 +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 Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "_jni/org_mozilla_jss_SecretDecoderRing_KeyManager.h"
#include <nspr.h>
#include <secitem.h>
#include <jss_exceptions.h>
#include <jssutil.h>
#include <pk11func.h>
#include <pk11util.h>
#include <Algorithm.h>
JNIEXPORT void JNICALL
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateKeyNative
(JNIEnv *env, jobject this, jobject tokenObj, jobject algObj,
jbyteArray keyIDba, jint keySize)
{
PK11SlotInfo *slot = NULL;
CK_MECHANISM_TYPE mech;
PK11SymKey *symk = NULL;
SECItem *keyID = NULL;
/* get the slot */
if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) {
goto finish;
}
if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/)
!= SECSuccess)
{
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to login to token");
goto finish;
}
/* get the key ID */
keyID = JSS_ByteArrayToSECItem(env, keyIDba);
if( keyID == NULL ) {
ASSERT_OUTOFMEM(env);
goto finish;
}
/* get the algorithm */
mech = JSS_getPK11MechFromAlg(env, algObj);
if( mech == CKM_INVALID_MECHANISM) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 "
"mechanism for key generation algorithm");
goto finish;
}
/* generate the key */
symk = PK11_TokenKeyGen(slot, mech, NULL /*param*/, keySize, keyID,
PR_TRUE /* isToken */, NULL /*wincx*/);
if( symk == NULL ) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to generate token symmetric key");
goto finish;
}
finish:
if( symk != NULL ) {
PK11_FreeSymKey(symk);
}
if( keyID != NULL ) {
SECITEM_FreeItem(keyID, PR_TRUE /*freeit*/);
}
return;
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateUniqueNamedKeyNative
(JNIEnv *env, jobject this, jobject tokenObj, jobject algObj,
jbyteArray keyIDba, jint keySize, jstring nickname)
{
PK11SlotInfo *slot = NULL;
CK_MECHANISM_TYPE mech;
PK11SymKey *symk = NULL;
SECItem *keyID = NULL;
const char *keyname = NULL;
SECStatus status;
/* get the slot */
if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) {
goto finish;
}
if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/)
!= SECSuccess)
{
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to login to token");
goto finish;
}
/* get the key ID */
keyID = JSS_ByteArrayToSECItem(env, keyIDba);
if( keyID == NULL ) {
ASSERT_OUTOFMEM(env);
goto finish;
}
/* get the algorithm */
mech = JSS_getPK11MechFromAlg(env, algObj);
if( mech == CKM_INVALID_MECHANISM) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 "
"mechanism for key generation algorithm");
goto finish;
}
/* generate the key */
symk = PK11_TokenKeyGen(slot, mech, NULL /*param*/, keySize, keyID,
PR_TRUE /* isToken */, NULL /*wincx*/);
if( symk == NULL ) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to generate token symmetric key");
goto finish;
}
/* convert the Java String into a native "C" string */
keyname = (*env)->GetStringUTFChars( env, nickname, 0 );
/* name the key */
status = PK11_SetSymKeyNickname( symk, keyname );
if( status != SECSuccess ) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to name token symmetric key");
}
finish:
if( symk != NULL ) {
PK11_FreeSymKey(symk);
}
if( keyID != NULL ) {
SECITEM_FreeItem(keyID, PR_TRUE /*freeit*/);
}
if( keyname != NULL ) {
/* free the native "C" string */
(*env)->ReleaseStringUTFChars(env, nickname, keyname);
}
return;
}
JNIEXPORT jobject JNICALL
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupKeyNative
(JNIEnv *env, jobject this, jobject tokenObj, jobject algObj,
jbyteArray keyIDba)
{
PK11SlotInfo *slot = NULL;
PK11SymKey *symk = NULL;
SECItem *keyID = NULL;
jobject symkObj = NULL;
CK_MECHANISM_TYPE mech;
/* get the slot */
if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) {
goto finish;
}
if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/)
!= SECSuccess)
{
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to login to token");
goto finish;
}
/* get the key ID */
keyID = JSS_ByteArrayToSECItem(env, keyIDba);
if( keyID == NULL ) {
ASSERT_OUTOFMEM(env);
goto finish;
}
/* get the algorithm */
mech = JSS_getPK11MechFromAlg(env, algObj);
if( mech == CKM_INVALID_MECHANISM) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 "
"mechanism for key generation algorithm");
goto finish;
}
symk = PK11_FindFixedKey(slot, mech, keyID, NULL /*wincx*/);
if( symk != NULL ) {
symkObj = JSS_PK11_wrapSymKey(env, &symk);
}
finish:
if( symk != NULL ) {
PK11_FreeSymKey(symk);
}
if( keyID != NULL ) {
SECITEM_FreeItem(keyID, PR_TRUE /*freeit*/);
}
return symkObj;
}
JNIEXPORT jobject JNICALL
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupUniqueNamedKeyNative
(JNIEnv *env, jobject this, jobject tokenObj, jobject algObj,
jstring nickname)
{
PK11SlotInfo *slot = NULL;
CK_MECHANISM_TYPE mech;
const char *keyname = NULL;
char *name = NULL;
int count = 0;
int keys_found = 0;
PK11SymKey *symKey = NULL;
PK11SymKey *nextSymKey = NULL;
jobject symKeyObj = NULL;
/* get the slot */
if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) {
goto finish;
}
if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/)
!= SECSuccess)
{
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to login to token");
goto finish;
}
/* get the algorithm -- although this is not currently used */
mech = JSS_getPK11MechFromAlg(env, algObj);
if( mech == CKM_INVALID_MECHANISM) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 "
"mechanism for key generation algorithm");
goto finish;
}
/* convert the Java String into a native "C" string */
keyname = (*env)->GetStringUTFChars( env, nickname, 0 );
/* initialize the symmetric key list. */
symKey = PK11_ListFixedKeysInSlot(
/* slot */ slot,
/* nickname */ NULL,
/* wincx */ NULL );
/* iterate through the symmetric key list. */
while( symKey != NULL ) {
name = PK11_GetSymKeyNickname( /* symmetric key */ symKey );
if( name != NULL ) {
if( keyname != NULL ) {
if( PL_strcmp( keyname, name ) == 0 ) {
keys_found++;
}
}
PORT_Free(name);
}
nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
PK11_FreeSymKey( /* symmetric key */ symKey );
symKey = nextSymKey;
count++;
}
/* case 1: the token is empty */
if( count == 0 ) {
/* the specified token is empty */
goto finish;
}
/* case 2: the specified key is not on this token */
if( ( keyname != NULL ) &&
( keys_found == 0 ) ) {
/* the key called "keyname" could not be found */
goto finish;
}
/* case 3: the specified key exists more than once on this token */
if( keys_found != 1 ) {
/* more than one key called "keyname" was found on this token */
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Duplicate named keys exist on this token");
goto finish;
}
/* Re-initialize the symmetric key list. */
symKey = PK11_ListFixedKeysInSlot(
/* slot */ slot,
/* nickname */ NULL,
/* wincx */ NULL );
/* Reiterate through the symmetric key list once more, */
/* this time returning an actual reference to the key. */
while( symKey != NULL ) {
name = PK11_GetSymKeyNickname( /* symmetric key */ symKey );
if( name != NULL ) {
if( keyname != NULL ) {
if( PL_strcmp( keyname, name ) == 0 ) {
symKeyObj = JSS_PK11_wrapSymKey(env, &symKey);
PORT_Free(name);
goto finish;
}
}
PORT_Free(name);
}
nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey );
PK11_FreeSymKey( /* symmetric key */ symKey );
symKey = nextSymKey;
}
finish:
if( symKey != NULL ) {
PK11_FreeSymKey(symKey);
}
if( keyname != NULL ) {
/* free the native "C" string */
(*env)->ReleaseStringUTFChars(env, nickname, keyname);
}
return symKeyObj;
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_SecretDecoderRing_KeyManager_deleteKeyNative
(JNIEnv *env, jobject this, jobject tokenObj, jobject key)
{
PK11SlotInfo *slot = NULL;
PK11SymKey *symk = NULL;
SECStatus status;
/* get the slot */
if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) {
goto finish;
}
if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/)
!= SECSuccess)
{
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to login to token");
goto finish;
}
/* get the key pointer */
if( JSS_PK11_getSymKeyPtr(env, key, &symk) != PR_SUCCESS) {
goto finish;
}
if( PK11_DeleteTokenSymKey(symk) != SECSuccess ) {
JSS_throwMsgPrErr(env, TOKEN_EXCEPTION,
"Failed to delete token symmetric key");
goto finish;
}
finish:
/* don't free symk or slot, they are owned by their Java objects */
return;
}

View File

@@ -1,316 +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 Network Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.SecretDecoderRing;
import java.security.*;
import javax.crypto.*;
import org.mozilla.jss.crypto.*;
import org.mozilla.jss.util.Assert;
/**
* Creates, finds, and deletes keys for SecretDecoderRing.
*/
public class KeyManager {
private static final int KEYID_LEN = 16;
private static final String RNG_ALG = "pkcs11prng";
private static final String RNG_PROVIDER = "Mozilla-JSS";
/**
* The default key generation algorithm, currently DES3.
*/
public static final KeyGenAlgorithm DEFAULT_KEYGEN_ALG =
KeyGenAlgorithm.DES3;
/**
* The default key size (in bytes). This is only relevant for algorithms
* with variable-length keys, such as AES.
*/
public static final int DEFAULT_KEYSIZE = 0;
private CryptoToken token;
/**
* Creates a new KeyManager using the given CryptoToken.
* @param token The token on which this KeyManager operates.
*/
public KeyManager(CryptoToken token) {
if( token == null ) {
throw new NullPointerException("token is null");
}
this.token = token;
}
/**
* Generates an SDR key with the default algorithm and key size.
* The default algorithm is stored in the constant DEFAULT_KEYGEN_ALG.
* The default key size is stored in the constant DEFAULT_KEYSIZE.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateKey() throws TokenException {
return generateKey(DEFAULT_KEYGEN_ALG, DEFAULT_KEYSIZE);
}
/**
* Generates an SDR key with the given algorithm and key size.
* @param keySize Length of key in bytes. This is only relevant for
* algorithms that take more than one key size. Otherwise it can just
* be set to 0.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateKey(KeyGenAlgorithm alg, int keySize)
throws TokenException
{
if( alg == null ) {
throw new NullPointerException("alg is null");
}
byte[] keyID = generateUnusedKeyID();
generateKeyNative(token, alg, keyID, keySize);
return keyID;
}
/**
* @param keySize Key length in bytes.
*/
private native void generateKeyNative(CryptoToken token,
KeyGenAlgorithm alg, byte[] keyID, int keySize);
/**
* Generates an SDR key with the default algorithm and key size.
* and names it with the specified nickname.
* The default algorithm is stored in the constant DEFAULT_KEYGEN_ALG.
* The default key size is stored in the constant DEFAULT_KEYSIZE.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateUniqueNamedKey(String nickname)
throws TokenException {
return generateUniqueNamedKey(DEFAULT_KEYGEN_ALG, DEFAULT_KEYSIZE,
nickname);
}
/**
* Generates an SDR key with the given algorithm, key size, and nickname.
* @param alg The algorithm that this key will be used for.
* This is necessary because it will be stored along with the
* key for later use by the security library.
* @param keySize Length of key in bytes. This is only relevant for
* algorithms that take more than one key size. Otherwise it can just
* be set to 0.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateUniqueNamedKey(KeyGenAlgorithm alg, int keySize,
String nickname)
throws TokenException
{
// always strip all preceding/trailing whitespace
// from passed-in String parameters
if( nickname != null ) {
nickname = nickname.trim();
}
if( alg == null ) {
throw new NullPointerException("alg is null");
}
// disallow duplicates (i. e. - symmetric keys with the same name)
if( uniqueNamedKeyExists(nickname) ) {
throw new NullPointerException("duplicate symmetric key");
}
byte[] keyID = generateUnusedKeyID();
generateUniqueNamedKeyNative(token, alg, keyID, keySize, nickname);
return keyID;
}
/**
* @param keySize Key length in bytes.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
*/
private native void generateUniqueNamedKeyNative(CryptoToken token,
KeyGenAlgorithm alg, byte[] keyID, int keySize, String nickname);
/**
* Generates a key ID that is currently unused on this token.
* The caller is responsible for synchronization issues that may arise
* if keys are generated by different threads.
*/
private byte[] generateUnusedKeyID() throws TokenException {
try {
SecureRandom rng = SecureRandom.getInstance(RNG_ALG, RNG_PROVIDER);
byte[] keyID = new byte[KEYID_LEN];
do {
rng.nextBytes(keyID);
} while( keyExists(keyID) );
return keyID;
} catch(NoSuchAlgorithmException nsae) {
throw new RuntimeException("No such algorithm: " + RNG_ALG);
} catch(NoSuchProviderException nspe) {
throw new RuntimeException("No such provider: " + RNG_PROVIDER);
}
}
private boolean keyExists(byte[] keyid) throws TokenException {
return (lookupKey(Encryptor.DEFAULT_ENCRYPTION_ALG, keyid) != null);
}
/**
* Looks up the key on this token with the given algorithm and key ID.
* @param alg The algorithm that this key will be used for.
* This is necessary because it will be stored along with the
* key for later use by the security library. It should match
* the actual algorithm of the key you are looking for. If you
* pass in a different algorithm and try to use the key that is returned,
* the results are undefined.
* @return The key, or <tt>null</tt> if the key is not found.
*/
public SecretKey lookupKey(EncryptionAlgorithm alg, byte[] keyid)
throws TokenException
{
if( alg == null || keyid == null ) {
throw new NullPointerException();
}
SymmetricKey k = lookupKeyNative(token, alg, keyid);
if( k == null ) {
return null;
} else {
return new SecretKeyFacade(k);
}
}
private native SymmetricKey lookupKeyNative(CryptoToken token,
EncryptionAlgorithm alg, byte[] keyid) throws TokenException;
public boolean uniqueNamedKeyExists(String nickname)
throws TokenException
{
return (lookupUniqueNamedKey(Encryptor.DEFAULT_ENCRYPTION_ALG,
nickname) != null);
}
/**
* Looks up the key on this token with the given algorithm and nickname.
* @param alg The algorithm that this key will be used for.
* This is necessary because it will be stored along with the
* key for later use by the security library. It should match
* the actual algorithm of the key you are looking for. If you
* pass in a different algorithm and try to use the key that is returned,
* the results are undefined.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
* @return The key, or <tt>null</tt> if the key is not found.
*/
public SecretKey lookupUniqueNamedKey(EncryptionAlgorithm alg,
String nickname)
throws TokenException
{
// always strip all preceding/trailing whitespace
// from passed-in String parameters
if( nickname != null ) {
nickname = nickname.trim();
}
if( alg == null || nickname == null || nickname.equals("") ) {
throw new NullPointerException();
}
SymmetricKey k = lookupUniqueNamedKeyNative(token, alg, nickname);
if( k == null ) {
return null;
} else {
return new SecretKeyFacade(k);
}
}
private native SymmetricKey lookupUniqueNamedKeyNative(CryptoToken token,
EncryptionAlgorithm alg, String nickname) throws TokenException;
/**
* Deletes the key with the given keyID from this token.
* @throws InvalidKeyException If the key does not exist on this token.
*/
public void deleteKey(byte[] keyID) throws TokenException,
InvalidKeyException
{
deleteKey(lookupKey(Encryptor.DEFAULT_ENCRYPTION_ALG, keyID));
}
/**
* If it exists, delete the key with the specified nickname from this
* token.
*/
public void deleteUniqueNamedKey(String nickname) throws TokenException,
InvalidKeyException
{
// only delete this symmetric key if it exists
if( uniqueNamedKeyExists(nickname) ) {
deleteKey(lookupUniqueNamedKey(Encryptor.DEFAULT_ENCRYPTION_ALG,
nickname));
}
}
/**
* Deletes this key from this token.
* @throws InvalidKeyException If the key does not reside on this token,
* or is not a JSS key.
*/
public void deleteKey(SecretKey key) throws TokenException,
InvalidKeyException
{
if( key == null ) {
throw new NullPointerException();
}
if( ! (key instanceof SecretKeyFacade) ) {
throw new InvalidKeyException("Key must be a JSS key");
}
deleteKeyNative(token, ((SecretKeyFacade)key).key);
}
private native void deleteKeyNative(CryptoToken token, SymmetricKey key)
throws TokenException;
}

View File

@@ -1,76 +0,0 @@
#! gmake
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/config.mk
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################

View File

@@ -1,41 +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 Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
TARGETS=$(LIBRARY)
SHARED_LIBRARY=
IMPORT_LIBRARY=
NO_MD_RELEASE = 1

View File

@@ -1,52 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
CORE_DEPTH = ../../../../..
MODULE = jss
NS_USE_JDK = 1
REQUIRES = nspr20 nss
PACKAGE = org/mozilla/jss/SecretDecoderRing
CSRCS = KeyManager.c \
$(NULL)
LIBRARY_NAME = jsssdr

View File

@@ -1,14 +0,0 @@
<html>
<body>
A facility for encrypting and decrypting small amounts of data with
a symmetric key. This is most commonly used for encrypting password files
to implement single sign-on.
<p>KeyManager is used to create, lookup, and delete the symmetric keys used
for SecretDecoderRing. Encryptor is used to encrypt data. Decryptor is used
to decrypt data that was previously encrypted with Encryptor. Encoding
and Encoding.Template are used internally, but they were made public
because they may occasionally be useful to applications.
</body>
</html>

View File

@@ -1,290 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import org.mozilla.jss.util.Assert;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/**
* Represents an ASN.1 <code>ANY</code> value. An ANY is just an arbitrary
* ASN.1 value. It can be thought of as the simplest implementation of the
* <code>ASN1Value</code> interface. Although they can be created
* from scratch (from raw BER), instances of <code>ANY</code> are usually
* found after decoding
* with a template that has an <code>ANY</code> field.
*
* <p>An <code>ANY</code> supports extracting the BER encoding, or decoding
* with a different template.
*/
public class ANY implements ASN1Value {
private ANY() { }
// The complete encoding of header + contents
private byte[] encoded;
private Tag tag;
/**
* Creates an ANY value, which is just a generic ASN.1 value.
* This method is provided for efficiency if the tag is already known,
* so that we don't have to parse the encoding for it.
* @param tag The tag of this value. It must be the same as the actual tag
* contained in the encoding.
* @param encoded The complete BER encoding of this value, including
* tag, form, length, and contents.
*/
public ANY(Tag tag, byte[] encoded) {
this.encoded = encoded;
this.tag = tag;
}
/**
* Creates an ANY value, which is just a generic ASN.1 value.
* @param encoded The complete BER encoding of this value, including
* tag, form, length, and contents.
*/
public ANY(byte[] encoded) throws InvalidBERException {
try {
this.encoded = encoded;
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
ASN1Header head = new ASN1Header(bis);
this.tag = head.getTag();
} catch(IOException e) {
throw new org.mozilla.jss.util.AssertionException(
"IOException while creating ANY: "+e);
}
}
/**
* Returns the tag of this value.
*/
public Tag getTag() {
return tag;
}
/**
* Returns the complete encoding of header and contents, as passed into
* the constructor or read from a BER input stream.
*/
public byte[] getEncoded() {
return encoded;
}
/**
* Returns the ASN.1 header from the encoding.
*/
public ASN1Header getHeader() throws InvalidBERException, IOException {
if( header == null ) {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
header = new ASN1Header(bis);
}
return header;
}
private ASN1Header header=null;
/**
* Strips out the header and returns just the contents octets of the
* encoding.
*/
private byte[] contents=null;
public byte[] getContents() throws InvalidBERException {
try {
if( contents==null ) {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
header = new ASN1Header(bis);
contents = new byte[ bis.available() ];
if( (contents.length != header.getContentLength()) &&
( header.getContentLength() != -1 ) ) {
throw new InvalidBERException("Length of contents was not the "+
"same as the header predicted");
}
ASN1Util.readFully(contents, bis);
}
return contents;
} catch( IOException e ) {
Assert.notReached("IOException reading from byte array");
return null;
}
}
public void encode(OutputStream ostream) throws IOException {
ostream.write(encoded);
}
/**
* Decodes this ANY using the given template. This is useful if you
* originally decoded something as an ANY because you didn't know
* what it was, but now you know what it is supposed to be.
*
* @param template The template to use to decode this ANY.
* @return The output of the given template when it is fed the
* encoding of this ANY.
*/
public ASN1Value decodeWith(ASN1Template template)
throws InvalidBERException
{
try {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(bis);
} catch( IOException e ) {
Assert.notReached("IOException while reading from byte array input"+
" stream");
return null;
}
}
/**
* Decodes this ANY using the given template. This is useful if you
* originally decoded something as an ANY because you didn't know
* what it was, but now you know what it is supposed to be.
*
* @param implicitTag The implicit tag for the encoding.
* @param template The template to use to decode this ANY.
* @return The output of the given template when it is fed the
* encoding of this ANY.
*/
public ASN1Value decodeWith(Tag implicitTag, ASN1Template template)
throws IOException, InvalidBERException
{
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(implicitTag, bis);
}
/**
* @param implicitTag <b>This parameter is ignored</b>, because
* ANY values cannot have implicit tags.
*/
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
if( ! implicitTag.equals(tag) ) {
Assert.notReached("No implicit tags allowed for ANY");
}
ostream.write(encoded);
}
/**
* Extracts the contents from the ANY and encodes them with
* the provided tag.
*/
public void encodeWithAlternateTag(Tag alternateTag, OutputStream ostream)
throws IOException, InvalidBERException
{
byte[] contents = getContents();
ASN1Header oldHead = getHeader();
Assert._assert( contents.length == oldHead.getContentLength() );
ASN1Header newHead = new ASN1Header( alternateTag, oldHead.getForm(),
contents.length);
newHead.encode(ostream);
ostream.write(contents);
}
/**
* Returns a singleton instance of a decoding template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static Template templateInstance = new Template();
/**
* A class for decoding <code>ANY</code> values from BER.
*/
public static class Template implements ASN1Template {
public boolean tagMatch(Tag tag) {
return true; // wheeeeee...it's ANY!
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = ASN1Header.lookAhead(istream);
if( head.getContentLength() == -1 ) {
// indefinite length encoding
ByteArrayOutputStream recording = new ByteArrayOutputStream();
// eat the header off the input stream
head = new ASN1Header(istream);
// write the header to the recording stream
recording.write( head.encode() );
// write all objects from the input stream to the recording
// stream, until we hit an END-OF-CONTENTS tag
ANY any;
ANY.Template anyt = new ANY.Template();
int count=0;
do {
any = (ANY) anyt.decode(istream);
recording.write( any.getEncoded() );
} while( ! any.getTag().equals(Tag.EOC) );
return new ANY( head.getTag(), recording.toByteArray() );
} else {
// definite length encoding
byte[] data = new byte[ (int) head.getTotalLength() ];
ASN1Util.readFully(data, istream);
return new ANY(head.getTag(), data);
}
} catch( InvalidBERException e ) {
throw new InvalidBERException(e, "ANY");
}
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
throw new InvalidBERException("Implicit tag on ANY");
}
} // End of Template
}

View File

@@ -1,414 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.math.BigInteger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.util.Vector;
import org.mozilla.jss.util.Assert;
/**
* The portion of a BER encoding that precedes the contents octets. Consists
* of the tag, form, and length octets.
*/
public class ASN1Header {
// This is set by the the decoding constructor, and by the encode()
// method. If it is set by the decoding constructor, it is supposed
// to represent what was actually read from the input stream, so it
// must not be overwritten later by the output of encode(), which could
// be a different encoding (DER vs. BER, for example).
private byte[] cachedEncoding = null;
/**
* Returns the length of the header plus the length of the contents;
* the total length of the DER encoding of an ASN1 value. Returns
* -1 if indefinite length encoding was used.
*/
public long getTotalLength() {
if( contentLength == -1 ) {
return -1;
} else {
return encode().length + contentLength;
}
}
private Tag tag;
public Tag getTag() {
return tag;
}
// -1 means indefinite length encoding
private long contentLength;
/**
* Returns -1 for indefinite length encoding.
*/
public long getContentLength() {
return contentLength;
}
// PRIMITIVE or CONSTRUCTED
public static final Form PRIMITIVE = Form.PRIMITIVE;
public static final Form CONSTRUCTED = Form.CONSTRUCTED;
private Form form;
/**
* Returns the Form, PRIMITIVE or CONSTRUCTED.
*/
public Form getForm() {
return form;
}
// This is the maximum size of ASN1 Header we support.
// 32 bytes is pretty huge, I've never seen anything bigger than 7.
private static final int MAX_LOOK_AHEAD = 32;
/**
* Returns information about the next item in the stream, but does not
* consume any octets.
* @exception IOException If the input stream does not support look ahead.
*/
public static ASN1Header lookAhead(InputStream derStream)
throws IOException, InvalidBERException
{
if( ! derStream.markSupported() ) {
throw new IOException("Mark not supported on this input stream");
}
derStream.mark(MAX_LOOK_AHEAD);
ASN1Header info = new ASN1Header(derStream);
derStream.reset();
return info;
}
/**
* Gets info about the next item in the DER stream, consuming the
* identifier and length octets.
*/
public ASN1Header(InputStream istream)
throws InvalidBERException, IOException
{
// default BAOS size is 32 bytes, which is plenty
ByteArrayOutputStream encoding = new ByteArrayOutputStream();
int inInt = istream.read();
if( inInt == -1 ) {
throw new InvalidBERException("End-of-file reached while "+
"decoding ASN.1 header");
}
encoding.write(inInt);
byte byte1 = (byte) inInt;
Tag.Class tagClass;
//
// Get Tag Class
//
tagClass = Tag.Class.fromInt( (byte1 & 0xff) >>> 6 );
//
// Get form
//
if( (byte1 & 0x20) == 0x20 ) {
form = CONSTRUCTED;
} else {
form = PRIMITIVE;
}
//
// Get Tag Number
//
long tagNum;
if( (byte1 & 0x1f) == 0x1f ) {
// long form
//
// read all octets into a Vector of Bytes
//
byte next;
Vector bV = new Vector();
// last byte has MSB == 0.
do {
inInt = istream.read();
if( inInt == -1 ) {
throw new InvalidBERException("End-of-file reached while"
+" decoding ASN.1 header");
}
encoding.write(inInt);
next = (byte) inInt;
bV.addElement( new Byte(next) );
} while( (next & 0x80) == 0x80 );
Assert._assert( bV.size() > 0 );
//
// Copy Vector of 7-bit bytes into array of 8-bit bytes.
//
byte[] bA = new byte[ ( (bV.size()*7) + 7 ) / 8 ];
int v; // vector index
int a; // array index
// clear the target array
for( a = 0; a < bA.length; a++ ) {
bA[a] = 0;
}
int shift = 0; // the amount the Vector is shifted from the array
// copy bits from the Vector to the array, going from the
// end (LSB) to the beginning (MSB).
a = bA.length - 1;
for( v=bV.size()-1 ; v >= 0; v--) {
Assert._assert( v >= 0 );
Assert._assert( v < bV.size() );
Assert._assert( a >= 0 );
Assert._assert( a < bA.length );
// MSB is not part of the number
byte b = (byte) ( ((Byte)bV.elementAt(v)).byteValue() & 0x7f );
bA[a] |= b << shift;
if( shift > 1 ) {
// The byte from the Vector falls across a byte boundary
// in the array. We've already got the less-significant
// bits, now copy the more-significant bits into
// the next element of the array.
Assert._assert( a > 0 );
--a;
bA[a] |= b >>> (8-shift);
}
shift = (shift+7)%8; // update shift
}
// Create a new unsigned BigInteger from the byte array
tagNum = (new BigInteger( 1, bA )).longValue();
} else {
// short form
tagNum = byte1 & 0x1f;
}
tag = new Tag(tagClass, tagNum);
//
// Get Length
//
inInt = istream.read();
if(inInt == -1) {
throw new InvalidBERException("End-of-file reached while "+
"decoding ASN.1 header");
}
encoding.write(inInt);
byte lenByte = (byte) inInt;
if( (lenByte & 0x80) == 0 ) {
// short form
contentLength = lenByte;
} else {
// long form
if( (lenByte & 0x7f) == 0 ) {
// indefinite
contentLength = -1;
} else {
// definite
byte[] lenBytes = new byte[ lenByte & 0x7f ];
ASN1Util.readFully(lenBytes, istream);
encoding.write( lenBytes );
contentLength = (new BigInteger( 1, lenBytes )).longValue();
}
}
// save our encoding so we don't have to recompute it later
cachedEncoding = encoding.toByteArray();
}
/**
* This constructor is to be called when we are constructing an ASN1Value
* rather than decoding it.
* @param contentLength Must be >=0. Although indefinite length
* <i>decoding</i> is supported, indefinite length <i>encoding</i>
* is not.
*/
public ASN1Header( Tag tag, Form form, long contentLength)
{
this.tag = tag;
this.form = form;
Assert._assert(contentLength >= 0);
this.contentLength = contentLength;
}
public void encode( OutputStream ostream )
throws IOException
{
ostream.write( encode() );
}
public byte[] encode() {
// It's important that we not recompute the encoding if it was
// set by ASN1Header(InputStream), since in that case it represents
// the encoding that was actually read from the InputStream.
if( cachedEncoding != null ) {
return cachedEncoding;
}
ByteArrayOutputStream cache = new ByteArrayOutputStream();
//
// Identifier octet(s)
//
byte idOctet = 0;
idOctet |= tag.getTagClass().toInt() << 6;
if( form == CONSTRUCTED ) {
idOctet |= 0x20;
}
if( tag.getNum() <= 30 ) {
// short form
idOctet |= (tag.getNum() & 0x1f );
cache.write( idOctet );
} else {
// long form
idOctet |= 0x1f;
BigInteger tagNum = BigInteger.valueOf(tag.getNum());
cache.write( idOctet );
int bitlength = tagNum.bitLength();
int reps = (bitlength+6)/7;
for( reps = reps-1; reps > 0 ; reps--) {
long shifted = tag.getNum() >>> ( 7*reps );
cache.write( (((byte)shifted) & 0x7f) | 0x80 );
}
cache.write( ((byte)tag.getNum()) & 0x7f );
}
//
// Length Octets
//
if( contentLength == -1 ) {
// indefinite form
cache.write( (byte) 0x80 );
} else if( contentLength <= 127 ) {
// short form
cache.write( (byte) contentLength );
} else {
// long form
byte[] val = unsignedBigIntToByteArray(
BigInteger.valueOf(contentLength) );
cache.write( ((byte)val.length) | 0x80 );
cache.write( val, 0, val.length );
}
cachedEncoding = cache.toByteArray();
return cachedEncoding;
}
/**
* Converts an unsigned BigInteger to a minimal-length byte array.
* This is necessary because BigInteger.toByteArray() attaches an extra
* sign bit, which could cause the size of the byte representation to
* be bumped up by an extra byte.
*/
public static byte[] unsignedBigIntToByteArray(BigInteger bi) {
// make sure it is not negative
Assert._assert( bi.compareTo(BigInteger.valueOf(0)) != -1 );
// find minimal number of bytes to hold this value
int bitlen = bi.bitLength(); // minimal number of bits, without sign
int bytelen;
if( bitlen == 0 ) {
// special case, since bitLength() returns 0
bytelen = 1;
} else {
bytelen = (bitlen + 7) / 8;
}
byte[] withSign = bi.toByteArray();
if( bytelen == withSign.length ) {
return withSign;
} else {
// trim off extra byte at the beginning
Assert._assert( bytelen == withSign.length - 1 );
Assert._assert( withSign[0] == 0 );
byte[] without = new byte[bytelen];
System.arraycopy(withSign,1, without, 0, bytelen);
return without;
}
}
/**
* Verifies that this header has the given tag and form.
* @exception InvalidBERException If the header's tag or form
* differ from those passed in.
*/
public void validate(Tag expectedTag, Form expectedForm)
throws InvalidBERException
{
validate(expectedTag);
if( getForm() != expectedForm ) {
throw new InvalidBERException("Incorrect form: expected ["+
expectedForm+"], found ["+getForm());
}
}
/**
* Verifies that this head has the given tag.
* @exception InvalidBERException If the header's tag differs from that
* passed in.
*/
public void validate(Tag expectedTag) throws InvalidBERException {
if( ! getTag().equals( expectedTag ) ) {
throw new InvalidBERException("Incorrect tag: expected ["+
expectedTag+"], found ["+getTag()+"]");
}
}
/**
* Returns <code>true</code> if this is a BER end-of-contents marker.
*/
public boolean isEOC() {
return( tag.equals(Tag.EOC) );
}
}

View File

@@ -1,76 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
/**
* An interface for decoding ASN1Values from their BER encodings.
*
* @see ASN1Value
*/
public interface ASN1Template {
/**
* Determines whether the given tag will satisfy this template.
*/
public boolean tagMatch(Tag tag);
/**
* Decodes an ASN1Value from the InputStream without an implicit tag.
* @param istream Must support marking (markSupported() == true).
* For example, ByteArrayInputStream and BufferedInputStream
* support marking, but FileInputStream does not. If your source
* does not support marking, you can wrap it in a
* BufferedInputStream.
*/
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException;
/**
* Decodes an ASN1Value from the InputStream with the given implicit
* tag.
* @param istream Must support marking (markSupported() == true).
* For example, ByteArrayInputStream and BufferedInputStream
* support marking, but FileInputStream does not. If your source
* does not support marking, you can wrap it in a
* BufferedInputStream.
*/
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException;
}

View File

@@ -1,117 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.*;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.util.Assert;
public class ASN1Util {
public static byte[] encode(ASN1Value val) {
return encode(val.getTag(), val);
}
public static byte[] encode(Tag implicitTag, ASN1Value val)
{
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
val.encode(implicitTag, bos);
return bos.toByteArray();
} catch( IOException e ) {
Assert.notReached("Encoding to byte array gave IOException");
return null;
}
}
public static ASN1Value decode(ASN1Template template, byte[] encoded)
throws InvalidBERException
{
try {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(bis);
} catch( IOException e ) {
Assert.notReached("Decoding from byte array gave IOException");
return null;
}
}
public static ASN1Value decode(Tag implicitTag, ASN1Template template,
byte[] encoded)
throws InvalidBERException
{
try {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(implicitTag, bis);
} catch( IOException e ) {
Assert.notReached("Decoding from byte array gave IOException");
return null;
}
}
/**
* Fills a byte array with bytes from an input stream. This method
* keeps reading until the array is filled, an IOException occurs, or EOF
* is reached. The byte array will be completely filled unless an
* exception is thrown.
*
* @param bytes A byte array which will be filled up.
* @param istream The input stream from which to read the bytes.
* @exception IOException If an IOException occurs reading from the
* stream, or EOF is reached before the byte array is filled.
*/
public static void readFully(byte[] bytes, InputStream istream)
throws IOException
{
int numRead=0;
while(numRead < bytes.length) {
int nr = istream.read(bytes, numRead, bytes.length-numRead);
if( nr == -1 ) {
throw new EOFException();
}
numRead += nr;
}
}
}

View File

@@ -1,66 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.OutputStream;
import java.io.IOException;
/**
* A value that can be decoded from BER and encoded to DER.
*
* @see ASN1Template
*/
public interface ASN1Value {
/**
* Returns the base tag for this type, not counting any tags
* that may be imposed on it by its context.
*/
public Tag getTag();
/**
* Write this value's DER encoding to an output stream using
* its own base tag.
*/
public void encode(OutputStream ostream) throws IOException;
/**
* Write this value's DER encoding to an output stream using
* an implicit tag.
*/
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException;
}

View File

@@ -1,319 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import org.mozilla.jss.util.Assert;
import java.math.BigInteger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.util.BitSet;
/**
* An ASN.1 <code>BIT STRING</code>, which is an ordered sequence of bits.
* The bits are stored the same way they are encoded in BER: as an array
* of bytes with 0-7 unused bits at the end.
*/
public class BIT_STRING implements ASN1Value {
private BIT_STRING() { }
private byte[] bits;
private int padCount;
private boolean removeTrailingZeroes = false;
/**
* @param bits The bits packed into an array of bytes, with padding
* at the end. The array may be empty (but not null), in which case
* <code>padCount</code> must be zero. The array is referenced,
* not cloned.
* @param padCount The number of padding bits at the end of the array.
* Must be in the range <code>[0,7]</code>.
* @exception NumberFormatException If <code>padCount</code> is not in
* the range <code>[0,7]</code>, or <code>bits</code> is
* empty and <code>padCount</code> is non-zero.
*/
public BIT_STRING(byte[] bits, int padCount)
throws NumberFormatException
{
if(padCount < 0 || padCount > 7) {
throw new NumberFormatException();
}
if(bits.length == 0 && padCount != 0) {
throw new NumberFormatException();
}
this.bits = bits;
this.padCount = padCount;
}
/**
* Constructs a BIT_STRING from a BitSet.
* @param bs A BitSet.
* @param numBits The number of bits to copy from the BitSet.
* This is necessary because the size of a BitSet is always padded
* up to a multiple of 64, but not all of these bits may
* be significant.
* @exception NumberFormatException If <code>numBits</code> is larger
* than <code>bs.size()</code> or less than zero.
*/
public BIT_STRING(BitSet bs, int numBits)
throws NumberFormatException
{
if( numBits < 0 || numBits > bs.size() ) {
throw new NumberFormatException();
}
// allocate enough bytes to hold all the bits
bits = new byte[(numBits+7) / 8];
padCount = (bits.length * 8) - numBits;
Assert._assert( padCount >= 0 && padCount <= 7);
for(int i=0; i < numBits; i++) {
if( bs.get(i) ) {
bits[i/8] |= 0x80 >>> (i%8);
}
}
}
/**
* Determines whether the DER-encoding of this bitstring will have
* its trailing zeroes removed. Generally, DER requires that trailing
* zeroes be removed when the bitstring is used to hold flags, but
* not when it is used to hold binary data (such as a public key).
* The default is <tt>false</tt>.
*/
public boolean getRemoveTrailingZeroes() {
return this.removeTrailingZeroes;
}
/**
* Determines whether the DER-encoding of this bitstring will have
* its trailing zeroes removed. Generally, DER requires that trailing
* zeroes be removed when the bitstring is used to hold flags, but
* not when it is used to hold binary data (such as a public key).
* The default is <tt>false</tt>. If this bit string is used to hold
* flags, you should set this to <tt>true</tt>.
*/
public void setRemoveTrailingZeroes(boolean removeTrailingZeroes) {
this.removeTrailingZeroes = removeTrailingZeroes;
}
/**
* Returns the bits packed into an array of bytes, with padding
* at the end. The array may be empty (but not null), in which case
* <code>padCount</code> must be zero. The array is referenced,
* not cloned.
*/
public byte[] getBits() {
return bits;
}
/**
* Copies this BIT STRING into a Java BitSet. Note that BitSet.size()
* will not accurately reflect the number of bits in the BIT STRING,
* because the size of a BitSet is always rounded up to the next multiple
* of 64. The extra bits will be set to 0.
*/
public BitSet toBitSet() {
BitSet bs = new BitSet();
int numBits = (bits.length * 8) - padCount;
for( int i=0; i < numBits; i++) {
if( (bits[i/8] & (0x80 >>> (i%8))) != 0 ) {
bs.set(i);
} else {
bs.clear(i);
}
}
return bs;
}
/**
* Copies this BIT STRING into a boolean array. Each element of the array
* represents one bit with <code>true</code> for 1 and <code>false</code>
* for 0.
*/
public boolean[] toBooleanArray() {
boolean[] array = new boolean[(bits.length*8) - padCount];
// all elements are set to false by default
for(int i=0; i < array.length; i++) {
if( (bits[i/8] & (0x80 >>> (i%8))) != 0 ) {
array[i] = true;
}
}
return array;
}
/**
* Returns the number of padding bits at the end of the array.
* Must be in the range <code>[0,7]</code>.
*/
public int getPadCount() {
return padCount;
}
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 3);
public static final Form FORM = Form.PRIMITIVE;
public Tag getTag() {
return TAG;
}
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
// force all unused bits to be zero, in support of DER standard.
if( bits.length > 0 ) {
bits[bits.length-1] &= (0xff << padCount);
}
int padBits;
int numBytes;
if( removeTrailingZeroes ) {
// first pare off empty bytes
numBytes = bits.length;
for( ; numBytes > 0; --numBytes) {
if( bits[numBytes-1] != 0 ) {
break;
}
}
// Now compute the number of unused bits. This includes any
// trailing zeroes, whether they are significant or not.
if( numBytes == 0 ) {
padBits = 0;
} else {
for( padBits=0; padBits < 8; ++padBits ) {
if( (bits[numBytes-1] & (1 << padBits)) != 0 ) {
break;
}
}
Assert._assert(padBits >=0 && padBits <= 7);
}
} else {
// Don't remove trailing zeroes. Just write the bits out as-is.
padBits = padCount;
numBytes = bits.length;
}
ASN1Header head = new ASN1Header(implicitTag, FORM, numBytes+1);
head.encode(ostream);
ostream.write(padBits);
ostream.write(bits, 0, numBytes);
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
/**
* A class for decoding a <code>BIT_STRING</code> from its BER encoding.
*/
public static class Template implements ASN1Template {
public boolean tagMatch(Tag tag) {
return( TAG.equals(tag) );
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(TAG, istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header( istream );
head.validate( implicitTag );
if( head.getContentLength() == -1 ) {
// indefinite length encoding
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int padCount=0;
ASN1Header ahead;
do {
ahead = ASN1Header.lookAhead(istream);
if( ! ahead.isEOC() ) {
if(padCount != 0 ) {
throw new InvalidBERException("Element of constructed "+
"BIT STRING has nonzero unused bits, but is not\n"+
"the last element of the construction.");
}
BIT_STRING.Template bst = new BIT_STRING.Template();
BIT_STRING bs = (BIT_STRING) bst.decode(istream);
bos.write( bs.getBits() );
padCount = bs.getPadCount();
}
} while( ! ahead.isEOC() );
// consume the EOC
ahead = new ASN1Header(istream);
return new BIT_STRING( bos.toByteArray(), padCount );
}
// First octet is the number of unused bits in last octet
int padCount = istream.read();
if( padCount == -1 ) {
throw new InvalidBERException.EOF();
} else if( padCount < 0 || padCount > 7 ) {
throw new InvalidBERException("Unused bits not in range [0,7]");
}
// get the rest of the octets
byte[] bits = new byte[ (int) head.getContentLength() - 1];
ASN1Util.readFully(bits, istream);
return new BIT_STRING(bits, padCount);
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "BIT STRING");
}
}
} // end of Template
}

View File

@@ -1,146 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
import java.io.UnsupportedEncodingException;
import org.mozilla.jss.util.Assert;
/**
* The ASN.1 type <i>BMPString</i>. BMPStrings use the Unicode character set.
* They are encoded and decoded in big-endian format using two octets.
*/
public class BMPString extends CharacterString implements ASN1Value {
/**
* Creates a new BMPString from an array of Java characters.
*/
public BMPString(char[] chars) throws CharConversionException {
super(chars);
}
/**
* Creates a new BMPString from a Java String.
*/
public BMPString(String s) throws CharConversionException {
super(s);
}
/**
* Returns the conversion object for converting between an encoded byte
* array an an array of Java characters.
*/
CharConverter getCharConverter() {
return converterInstance;
}
private static final BMPConverter converterInstance = new BMPConverter();
static final Tag TAG = new Tag( Tag.UNIVERSAL, 30 );
static final Form FORM = Form.PRIMITIVE;
public Tag getTag() {
return TAG;
}
/**
* Returns a singleton instance of BMPString.Template. This is more
* efficient than creating a new BMPString.Template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template implements ASN1Template
{
protected Tag getTag() {
return TAG;
}
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
protected CharConverter getCharConverter() {
return new BMPConverter();
}
protected CharacterString generateInstance(char[] chars)
throws CharConversionException
{
return new BMPString(chars);
}
protected String typeName() {
return "BMPString";
}
}
private static class BMPConverter implements CharConverter {
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException
{
try {
String s = new String(bytes, offset, len, "UnicodeBig");
return s.toCharArray();
} catch( UnsupportedEncodingException e ) {
String err = "Unable to find UnicodeBig encoding mechanism";
Assert.notReached(err);
throw new CharConversionException(err);
}
}
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException
{
try {
// We don't want the byte-order mark
String s = new String(chars, offset, len);
return s.getBytes("UnicodeBigUnmarked");
} catch( UnsupportedEncodingException e ) {
String err = "Unable to find UnicodeBigUnmarked encoding mechanism";
Assert.notReached(err);
throw new CharConversionException(err);
}
}
} // end of char converter
}

View File

@@ -1,150 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* An ASN.1 <code>BOOLEAN</code> value.
*/
public class BOOLEAN implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 1);
public static final Form FORM = Form.PRIMITIVE;
public Tag getTag() {
return TAG;
}
private ASN1Header getHeader() {
return getHeader(TAG);
}
private ASN1Header getHeader(Tag implicitTag) {
return new ASN1Header(implicitTag, FORM, 1 );
}
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
getHeader(implicitTag).encode(ostream);
if( val ) {
ostream.write( 0xff );
} else {
ostream.write( 0x00 );
}
}
private BOOLEAN() { }
private boolean val;
/**
* Creates a <code>BOOLEAN</code> with the given value.
*/
public BOOLEAN(boolean val) {
this.val = val;
}
/**
* Returns the boolean value of this <code>BOOLEAN</code>.
*/
public boolean toBoolean() {
return val;
}
/**
* Returns "true" or "false".
*/
public String toString() {
if(val) {
return "true";
} else {
return "false";
}
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
/**
* A Class for decoding <code>BOOLEAN</code> values from their BER
* encodings.
*/
public static class Template implements ASN1Template {
public boolean tagMatch(Tag tag) {
return( tag.equals( BOOLEAN.TAG ) );
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(TAG, istream);
}
public ASN1Value decode(Tag tag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header(istream);
head.validate(tag, FORM);
int b = istream.read();
if( b == -1 ) {
throw new InvalidBERException("End-of-file reached while "+
"decoding BOOLEAN");
}
if( b == 0x00 ) {
return new BOOLEAN(false);
} else {
return new BOOLEAN(true);
}
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "BOOLEAN");
}
}
}
}

View File

@@ -1,288 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import org.mozilla.jss.util.Assert;
/**
* Objects of this class are generated by CHOICE.Template.decode(). It is
* not necessary to use them to encode a CHOICE. Since the encoding of a
* CHOICE is simply the encoding of the chosen element, it is easier
* to just write out the chosen element.
*/
public class CHOICE implements ASN1Value {
private CHOICE() { }
private Tag tag;
private ASN1Value val;
/**
* Create a CHOICE whose chosen element has an implicit tag.
*/
public CHOICE(Tag implicitTag, ASN1Value val) {
tag = implicitTag;
this.val = val;
}
/**
* Create a CHOICE whose chosen element has no implicit tag.
*/
public CHOICE(ASN1Value val) {
this.tag = val.getTag();
this.val = val;
}
/**
* Returns the tag that the chosen element is encoded with, which is
* either the underlying tag of the element or an implicit tag.
*/
public Tag getTag() {
return tag;
}
/**
* Returns the chosen value.
*/
public ASN1Value getValue() {
return val;
}
public static CHOICE.Template getTemplate() {
return new CHOICE.Template();
}
/**
* Encodes this CHOICE. This merely consists of encoding the chosen
* element with an implicit tag, if one was given in the constructor,
* or with its own underlying tag.
*/
public void encode( OutputStream ostream ) throws IOException {
val.encode( tag, ostream );
}
/**
* Encodes this CHOICE. This merely consists of encoding the chosen
* element with an implicit tag, if one was given in the constructor,
* or with its own underlying tag.
*
* @param implicitTag <b>This value is ignored</b>. The tag of a CHOICE
* is merely the tag of the chosen element of the CHOICE. A
* CHOICE cannot itself have an implicit tag.
*/
public void encode( Tag implicitTag, OutputStream ostream )
throws IOException
{
Assert._assert(implicitTag.equals(tag));
val.encode( tag, ostream );
}
/**
* A Template for decoding ASN.1 <code>CHOICE</code>s
*/
public static class Template implements ASN1Template {
// The the various possibilities in this CHOICE
private Vector templates = new Vector();
/**
* Creates an empty CHOICE template
*/
public Template() { }
/**
* Adds a new sub-template to this CHOICE template with no implicit tag.
*/
public void addElement( ASN1Template template ) {
templates.addElement( new Element( template ) );
}
/**
* Adds a new sub-template to this CHOICE template with an implicit tag.
*/
public void addElement( Tag implicitTag, ASN1Template template) {
templates.addElement( new Element( implicitTag, template) );
}
/**
* Returns the number of elements in this CHOICE template.
*/
public int size() {
return templates.size();
}
/**
* Retrieves the element at the specified index.
*/
public ASN1Template elementAt(int index) {
return ((Element)templates.elementAt(index)).getTemplate();
}
/**
* Retrieves the implicit tag of the element at the specified index.
* Returns null if there is no implicit tag for this element.
*/
public Tag implicitTagAt(int index) {
return ((Element)templates.elementAt(index)).getImplicitTag();
}
/**
* Empties this CHOICE template.
*/
public void removeAllElements() {
templates.removeAllElements();
}
/**
* Removes the element at the specified index.
*/
public void removeElementAt(int index) {
templates.removeElementAt(index);
}
/**
* Determines whether the given tag will satisfy this template.
* For a CHOICE, this is true if the tag satisfies any sub-template.
*/
public boolean tagMatch(Tag t) {
int size = size();
for(int i = 0; i < size; i++) {
Tag impl = implicitTagAt(i);
if( impl != null ) {
// There is an implicit tag, if we match it we have a match
if( impl.equals(t) ) {
return true;
}
} else {
// no implicit tag, look at the sub-template itself
ASN1Template templ = elementAt(i);
if( templ.tagMatch(t) ) {
return true;
}
}
}
// none of the elements matched
return false;
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
ASN1Header head = ASN1Header.lookAhead(istream);
Tag tag = head.getTag();
// Loop over all the elements of the CHOICE template until we
// find one with a matching tag.
int size = size();
for(int i=0; i < size; i++) {
if( implicitTagAt(i) != null ) {
if( implicitTagAt(i).equals(tag) ) {
// match by implicit tag!
ASN1Value val = elementAt(i).decode( implicitTagAt(i),
istream );
//return elementAt(i).decode( implicitTagAt(i), istream );
return new CHOICE( implicitTagAt(i), val );
}
} else {
if( elementAt(i).tagMatch(tag) ) {
// match by base tag !
//return elementAt(i).decode(istream);
return new CHOICE( elementAt(i).decode(istream) );
}
}
}
// we didn't find any match
throw new InvalidBERException("Unable to decode CHOICE");
}
// Implicit tags are illegal for CHOICE (and ANY)
/**
* Decodes a CHOICE.
* @param implicitTag <b>This parameter is ignored.</b> A choice
* cannot have an implicit tag.
*/
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
return decode(istream);
}
/**
* An element in a CHOICE template, consisting of a nested template
* and, optionally, an implicit tag for that template.
*/
private static class Element {
private ASN1Template template;
private Tag implicitTag=null;
/**
* Creates a CHOICE template element with no implicit tag.
*/
public Element(ASN1Template template) {
this.template = template;
}
/**
* Creates a CHOICE template element with an implicit tag.
*/
public Element(Tag implicitTag, ASN1Template template) {
this.template = template;
this.implicitTag = implicitTag;
}
/**
* Returns the template of this CHOICE template element.
*/
public ASN1Template getTemplate() {
return template;
}
/**
* Returns the implicit tag for this CHOICE template element,
* if there is one. If not, returns null.
*/
public Tag getImplicitTag() {
return implicitTag;
}
}
}
}

View File

@@ -1,48 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
interface CharConverter {
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException;
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException;
}

View File

@@ -1,188 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
/**
* An abstract base class for all character string types in ASN.1.
*/
public abstract class CharacterString implements ASN1Value {
abstract CharConverter getCharConverter();
public abstract Tag getTag();
static final Form FORM = Form.PRIMITIVE;
private char[] chars;
/**
* Converts this ASN.1 character string to a Java String.
*/
public String toString() {
return new String(chars);
}
/**
* Converts this ASN.1 character string to an array of Java characters.
*/
public char[] toCharArray() {
return chars;
}
protected CharacterString(char[] chars) throws CharConversionException {
this.chars = chars;
cachedContents = computeContents();
}
protected CharacterString(String s) throws CharConversionException {
this.chars = s.toCharArray();
cachedContents = computeContents();
}
private byte[] cachedContents;
private byte[] getEncodedContents() {
return cachedContents;
}
private byte[] computeContents() throws CharConversionException {
CharConverter converter = getCharConverter();
byte[] contents = converter.charToByte(chars, 0, chars.length);
return contents;
}
public void encode(OutputStream ostream) throws IOException {
encode( getTag(), ostream );
}
public void encode( Tag implicitTag, OutputStream ostream )
throws IOException
{
byte[] contents = getEncodedContents();
ASN1Header head = new ASN1Header( implicitTag, FORM, contents.length);
head.encode(ostream);
ostream.write( contents );
}
public abstract static class Template implements ASN1Template {
/**
* Must be overridden to return the tag for the subclass.
*/
protected abstract Tag getTag();
public abstract boolean tagMatch(Tag tag);
/**
* Must be overridden to return the correct character converter
* for the subclass.
*/
protected abstract CharConverter getCharConverter();
/**
* Must be overridden to create an instance of the subclass given
* a char array.
*/
protected abstract CharacterString generateInstance(char[] chars)
throws CharConversionException;
/**
* Must be overridden to provide the name of the subclass, for including
* into error messages.
*/
protected abstract String typeName();
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(getTag(), istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag);
byte[] raw; // raw bytes, not translated to chars yet
if( head.getContentLength() == -1 ) {
// indefinite length encoding
ASN1Header ahead;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
do {
ahead = ASN1Header.lookAhead( istream );
if( ! ahead.isEOC() ) {
OCTET_STRING.Template ot = new OCTET_STRING.Template();
OCTET_STRING os = (OCTET_STRING) ot.decode(istream);
bos.write( os.toByteArray() );
}
} while( ! ahead.isEOC() );
// consume EOC
ahead = new ASN1Header(istream);
raw = bos.toByteArray();
} else {
// definite length
raw = new byte[ (int) head.getContentLength() ];
ASN1Util.readFully(raw, istream);
}
char[] chars = getCharConverter().byteToChar(raw, 0, raw.length);
return generateInstance(chars);
} catch( CharConversionException e ) {
throw new InvalidBERException(e.getMessage());
} catch( InvalidBERException e ) {
throw new InvalidBERException(e, typeName());
}
}
}
}

View File

@@ -1,137 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.*;
/**
* This class keeps track of the number of bytes that have been read from
* a stream. It will be incremented by the number of bytes read or skipped.
* If the stream is marked and then reset, the number of bytes read will
* be reset as well.
*/
class CountingStream extends InputStream {
private int count=0;
private int markpos;
private InputStream source;
private static final boolean DEBUG = false;
private CountingStream() { }
public CountingStream(InputStream source) {
this.source = source;
}
public int available() throws IOException {
return source.available();
}
public void mark(int readlimit) {
source.mark(readlimit);
markpos = count;
if(DEBUG) {
System.out.println("Marked at position "+markpos);
}
}
public boolean markSupported() {
return source.markSupported();
}
public int read() throws IOException {
int n = source.read();
if( n != -1 ) {
count++;
if(DEBUG) {
System.out.println("read() 1 byte, count="+count);
}
}
return n;
}
public int read(byte[] buffer) throws IOException {
int n = source.read(buffer);
if( n != -1 ) {
count += n;
}
if(DEBUG) {
System.out.println("read([]) "+n+" bytes, count="+count);
}
return n;
}
public int read(byte[] buffer, int offset, int count) throws IOException {
int n = source.read(buffer, offset, count);
if( n != -1 ) {
this.count += n;
}
if(DEBUG) {
System.out.println("read(...) "+n+" bytes, count="+this.count);
}
return n;
}
public void reset() throws IOException {
source.reset();
if(DEBUG) {
System.out.println("reset from "+count+" to "+markpos);
}
count = markpos;
}
public long skip(long count) throws IOException {
this.count += count;
if(DEBUG) {
System.out.println("skipped "+count+", now at "+this.count);
}
return source.skip(count);
}
public int getNumRead() {
return count;
}
public void resetNumRead() {
count = 0;
markpos = 0;
if(DEBUG) {
System.out.println("resetting count to 0");
}
}
}

View File

@@ -1,117 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
/**
* Represents an ASN.1 <code>ENUMERATED</code> value. This has the same
* interface as <code>INTEGER</code>
*/
public class ENUMERATED extends INTEGER implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 10);
public Tag getTag() {
return TAG;
}
/**
* Creates a new ENUMERATED value from a long.
*/
public ENUMERATED( long val ) {
super( val );
}
ENUMERATED( byte[] valBytes ) {
super( valBytes );
}
/**
* Returns the value as a long.
*/
public long getValue() {
return longValue();
}
private static final ENUMERATED.Template templateInstance =
new ENUMERATED.Template();
public static ASN1Template getTemplate() {
return templateInstance;
}
/**
* A template for decoding ENUMERATED values from their BER encodings.
* The template reads the value as an INTEGER. It does not check that it
* is a valid value for the ENUMERATED type.
*/
public static class Template
extends INTEGER.Template implements ASN1Template
{
Tag getTag() {
return ENUMERATED.TAG;
}
public boolean tagMatch(Tag tag) {
return( tag.equals(ENUMERATED.TAG) );
}
public ASN1Value
decode(Tag tag, InputStream derStream)
throws InvalidBERException, IOException
{
try {
ASN1Header wrapper = new ASN1Header(derStream);
wrapper.validate(tag, FORM);
// Is length < 1 ?
if( wrapper.getContentLength() < 1 ) {
throw new InvalidBERException("Invalid 0 length for ENUMERATED");
}
byte[] valBytes = new byte[ (int) wrapper.getContentLength() ];
ASN1Util.readFully(valBytes, derStream);
return new ENUMERATED( valBytes );
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "ENUMERATED");
}
}
} // end of Template
}

View File

@@ -1,178 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import org.mozilla.jss.util.Assert;
/**
* An explicit tag.
*/
public class EXPLICIT implements ASN1Value {
public static final Form FORM = Form.CONSTRUCTED;
private ASN1Value content;
private Tag tag;
private EXPLICIT() { }
/**
* Creates an EXPLICIT tag wrapping some other ASN1Value. For example,
* for the following ASN.1 snippet:
* <pre>
* MyType [3] EXPLICIT INTEGER
* </pre>
* assuming a sample value of 5 for the INTEGER, a MyType could be
* created with:
* <pre>
* EXPLICIT myValue = new EXPLICIT( new Tag(3), new INTEGER(5) );
* </pre>
*/
public EXPLICIT( Tag tag, ASN1Value content ) {
Assert._assert(tag!=null && content!=null);
this.content = content;
this.tag = tag;
}
/**
* Returns the ASN1Value that is wrapped by this EXPLICIT tag.
*/
public ASN1Value getContent() {
return content;
}
/**
* Returns the Tag of this EXPLICIT tag.
*/
public Tag getTag() {
return tag;
}
public void encode(OutputStream ostream) throws IOException {
encode(tag, ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
content.encode(bos);
byte[] contentBytes = bos.toByteArray();
ASN1Header head = new ASN1Header(implicitTag, FORM,
contentBytes.length );
head.encode(ostream);
ostream.write(contentBytes);
}
public static Template getTemplate( Tag tag, ASN1Template content) {
return new Template(tag, content);
}
/**
* A template for decoding an object wrapped in an EXPLICIT tag.
*/
public static class Template implements ASN1Template {
private ASN1Template content;
private Tag tag;
private Template() { }
/**
* Creates a template for unwrapping an object wrapped in an explicit tag.
* For example, to decode:
* <pre>
* MyValue ::= [3] EXPLICIT INTEGER
* </pre>
* use:
* <pre>
* EXPLICIT.Template myTemplate = new EXPLICIT.Template( new Tag(3),
* new INTEGER.Template() );
* </pre>
*
* @param tag The tag value of the EXPLICIT tag.
* @param content The template for decoding the object that is wrapped
* in the explicit tag.
*/
public Template(Tag tag, ASN1Template content) {
this.content = content;
this.tag = tag;
}
public boolean tagMatch(Tag tag) {
return( this.tag.equals(tag) );
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(tag, istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header(istream);
head.validate( implicitTag, FORM.CONSTRUCTED );
ASN1Value val = content.decode(istream);
EXPLICIT e = new EXPLICIT(tag, val);
// if indefinite content length, consume the end-of-content marker
if( head.getContentLength() == -1 ) {
head = new ASN1Header(istream);
if( ! head.isEOC() ) {
throw new InvalidBERException("No end-of-contents marker");
}
}
return e;
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "EXPLICIT");
}
}
} // end of Template
}

View File

@@ -1,51 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
/**
* An exception thrown when an optional field is not present.
*/
public class FieldNotPresentException extends java.lang.Exception
{
public FieldNotPresentException() {
super();
}
public FieldNotPresentException(String msg) {
super(msg);
}
}

View File

@@ -1,57 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
/**
* An enumerated type representing the forms of an ASN.1 value.
* The possibilities are PRIMITIVE and CONSTRUCTED.
*/
public class Form {
private String name;
private Form() { }
private Form(String name) {
this.name = name;
}
public static final Form PRIMITIVE = new Form("PRIMITIVE");
public static final Form CONSTRUCTED = new Form("CONSTRUCTED");
public String toString() {
return name;
}
}

View File

@@ -1,95 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.mozilla.jss.util.Assert;
/**
* The ASN.1 type <code>GeneralizedTime</code>
*/
public class GeneralizedTime extends TimeBase implements ASN1Value {
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 24);
public Tag getTag() {
return TAG;
}
/**
* Creates a <code>GeneralizedTime</code> from a Date.
*/
public GeneralizedTime(Date date) {
super(date);
}
protected boolean isUTC() {
return false;
}
private static final GeneralizedTime.Template templateInstance =
new GeneralizedTime.Template();
public static GeneralizedTime.Template getTemplate() {
return templateInstance;
}
/**
* A class for decoding <code>GeneralizedTime</code>s.
*/
public static class Template extends TimeBase.Template
implements ASN1Template
{
protected Tag getTag() {
return TAG;
}
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
protected boolean isUTC() {
return false;
}
protected TimeBase generateInstance(Date date) {
return new GeneralizedTime(date);
}
}
}

View File

@@ -1,130 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
public class IA5String extends CharacterString implements ASN1Value {
public IA5String(char[] chars) throws CharConversionException {
super(chars);
}
public IA5String(String s) throws CharConversionException {
super(s);
}
CharConverter getCharConverter() {
return new IA5Converter();
}
public static final Tag TAG = new Tag( Tag.Class.UNIVERSAL, 22 );
public Tag getTag() {
return TAG;
}
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template implements ASN1Template
{
public Tag getTag() {
return IA5String.TAG;
}
public boolean tagMatch(Tag tag) {
return( tag.equals( IA5String.TAG ));
}
protected CharConverter getCharConverter() {
return new IA5Converter();
}
protected CharacterString generateInstance(char[] chars)
throws CharConversionException
{
return new IA5String(chars);
}
protected String typeName() {
return "IA5String";
}
}
// nested class
private static class IA5Converter implements CharConverter {
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException
{
char[] chars = new char[len];
int c; // char index
int b; // byte index
for(b = offset, c=0; c < len; b++, c++) {
if( (bytes[b] & 0x80) != 0 ) {
throw new CharConversionException("Invalid character: "+
bytes[b]);
}
chars[c] = (char) (bytes[b] & 0x7f);
}
return chars;
}
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException
{
byte[] bytes = new byte[len];
int c; // char index
int b; // byte index
for(c = offset, b = 0; b < len; c++, b++) {
if( (chars[c] & 0x7f) != chars[c] ) {
throw new CharConversionException("Invalid character: "+
chars[c]);
}
bytes[b] = (byte) (chars[c] & 0x7f);
}
return bytes;
}
}
}

View File

@@ -1,257 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.util.Random;
/**
* The ASN.1 type <code>INTEGER</code>. This class extends BigInteger.
*/
public class INTEGER extends BigInteger implements ASN1Value {
private byte[] encodedContents = null;
private byte[] getEncodedContents() {
if( encodedContents == null ) {
encodedContents = toByteArray();
}
return encodedContents;
}
private ASN1Header getHeader(Tag t) {
return new ASN1Header( t, FORM, getContentLength() );
}
public INTEGER(String s) throws NumberFormatException {
super(s);
}
public INTEGER(String s, int r) throws NumberFormatException {
super(s, r);
}
public INTEGER(byte[] bval) throws NumberFormatException {
super(bval);
}
public INTEGER(int sign, byte[] mag) throws NumberFormatException {
super(sign, mag);
}
public INTEGER(int numBits, Random rnd) throws NumberFormatException {
super(numBits, rnd);
}
public INTEGER(int bitLength, int certainty, Random rnd) {
super(bitLength, certainty, rnd);
}
public INTEGER(long val) {
super( BigInteger.valueOf(val).toByteArray() );
}
public INTEGER(BigInteger bi) {
super( bi.toByteArray() );
}
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 2);
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
public void encode(OutputStream outStream) throws IOException {
encode(getTag(), outStream);
}
public void encode(Tag implicitTag, OutputStream outStream)
throws IOException
{
// write header
getHeader(implicitTag).encode( outStream );
// write contents
outStream.write( getEncodedContents() );
}
public long getContentLength() {
return getEncodedContents().length;
}
public byte[] encode() throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
encode(b);
return b.toByteArray();
}
private static final INTEGER.Template templateInstance =
new INTEGER.Template();
public static ASN1Template getTemplate() {
return templateInstance;
}
/**
* Tests the DER encoding and decoding of the INTEGER class.
*/
public static void main(String args[]) {
try {
int[] Is = new int[11];
int[][] Bs = new int[11][];
int i = 0;
Is[i] = 0;
Bs[i++] = new int[]{ 0x02, 0x01, 0x00 };
Is[i] = 1;
Bs[i++] = new int[]{ 0x02, 0x01, 0x01 };
Is[i] = -1;
Bs[i++] = new int[]{ 0x02, 0x01, 0xff };
Is[i] = 127;
Bs[i++] = new int[]{ 0x02, 0x01, 0x7f };
Is[i] = 128;
Bs[i++] = new int[]{ 0x02, 0x02, 0x00, 0x80 };
Is[i] = 255;
Bs[i++] = new int[]{ 0x02, 0x02, 0x00, 0xff };
Is[i] = 256;
Bs[i++] = new int[]{ 0x02, 0x02, 0x01, 0x00 };
Is[i] = -128;
Bs[i++] = new int[]{ 0x02, 0x01, 0x80 };
Is[i] = -129;
Bs[i++] = new int[]{ 0x02, 0x02, 0xff, 0x7f };
Is[i] = 43568;
Bs[i++] = new int[]{ 0x02, 0x03, 0x00, 0xaa, 0x30 };
Is[i] = -43568;
Bs[i++] = new int[]{ 0x02, 0x03, 0xff, 0x55, 0xd0 };
for( i = 0; i < Is.length; i++) {
INTEGER I = new INTEGER( Is[i] );
byte[] compare = I.encode();
if( ! arraysEqual(compare, Bs[i]) ) {
System.err.println("Encoding FAILED: "+Is[i]);
System.exit(-1);
}
ByteArrayInputStream bis = new ByteArrayInputStream(compare);
Template template = new Template();
INTEGER create = (INTEGER) template.decode(bis);
if( create.intValue() != Is[i] ) {
System.err.println("Decoding FAILED: "+Is[i]);
System.exit(-1);
}
}
System.out.println("PASS");
} catch( Exception e ) {
e.printStackTrace();
}
}
private static boolean arraysEqual(byte[] bytes, int[] ints) {
if(bytes == null || ints == null) {
return false;
}
if(bytes.length != ints.length) {
return false;
}
for( int i=0; i < bytes.length; i++) {
if( bytes[i] != (byte)ints[i] ) {
return false;
}
}
return true;
}
///////////////////////////////////////////////////////////////////////
// INTEGER.Template
// This is a nested class.
//
public static class Template implements ASN1Template {
Tag getTag() {
return INTEGER.TAG;
}
public boolean tagMatch(Tag tag) {
return( tag.equals(INTEGER.TAG));
}
public ASN1Value
decode(InputStream derStream)
throws InvalidBERException, IOException
{
return decode( getTag(), derStream );
}
public ASN1Value
decode(Tag tag, InputStream derStream)
throws InvalidBERException, IOException
{
try {
ASN1Header wrapper = new ASN1Header(derStream);
wrapper.validate(tag, FORM);
// Is length < 1 ?
if( wrapper.getContentLength() < 1 ) {
throw new InvalidBERException("Invalid 0 length for INTEGER");
}
byte[] valBytes = new byte[ (int) wrapper.getContentLength() ];
ASN1Util.readFully(valBytes, derStream);
return new INTEGER( valBytes );
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "INTEGER");
}
}
} // end of class Template
}

View File

@@ -1,106 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.util.Vector;
/**
* An exception thrown when BER decoding fails.
*/
public class InvalidBERException extends java.lang.Exception {
private InvalidBERException child=null;
private Vector mesgList = new Vector();
public InvalidBERException(String mesg) {
super(mesg);
}
public void append(String mesg) {
mesgList.addElement(mesg);
}
public InvalidBERException(InvalidBERException e, String mesg) {
super(mesg);
child = e;
}
/**
* Prints out the exception class and error message, including
* all the nested exceptions.
*/
private void appendMessages(StringBuffer sb) {
int numMessages = mesgList.size();
for( int i=numMessages-1; i >= 0; --i ) {
sb.append(mesgList.elementAt(i));
sb.append(" >> ");
}
sb.append(getMessage());
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append( this.getClass().getName() );
sb.append(": ");
appendMessages(sb);
return sb.toString();
}
public String toStringNested() {
StringBuffer sb = new StringBuffer();
appendMessages(sb);
if( child != null ) {
sb.append(" >> ");
sb.append( child.toStringNested() );
}
return sb.toString();
}
public static class EOF extends InvalidBERException {
public EOF() {
super("Unexpected end-of-file encountered");
}
}
public static class InvalidChar extends InvalidBERException {
public InvalidChar(byte b, int offset) {
super("Invalid character ("+b+") encountered at offset "+offset);
}
public InvalidChar(char c, int offset) {
super("Invalid character ("+c+") encountered at offset"+offset);
}
}
}

View File

@@ -1,83 +0,0 @@
#! gmake
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape Security Services for Java.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# 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 *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/$(MODULE)/config/config.mk
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
#include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
run:
$(DEBUG_CMD) /share/builds/components/jdk/1.2.2_05a/SunOS/jre/bin/java -classpath $(JAVA_HOME)/lib/classes.zip:$(SOURCE_CLASSES_DIR)_DBG org.mozilla.jss.asn1.SEQUENCE /tmp/p10

View File

@@ -1,106 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
public class NULL implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 5);
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
ASN1Header head = new ASN1Header(implicitTag, FORM, 0);
head.encode(ostream);
}
private static final NULL instance = new NULL();
public static NULL getInstance() {
return instance;
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
public static class Template implements ASN1Template {
public Tag getTag() {
return NULL.TAG;
}
public boolean tagMatch(Tag tag) {
return( tag.equals(NULL.TAG) );
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(getTag(), istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag, FORM);
if( head.getContentLength() != 0 ) {
throw new InvalidBERException("Invalid length ("+
head.getContentLength()+") for NULL; only 0 is permitted");
}
return new NULL();
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "NULL");
}
}
} // end of Template
}

View File

@@ -1,524 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.mozilla.jss.util.Assert;
import java.util.Vector;
import java.util.StringTokenizer;
public class OBJECT_IDENTIFIER implements ASN1Value {
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Standard object identifiers
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
/**
* The OID space for RSA Data Security, Inc.
*/
public static final OBJECT_IDENTIFIER RSADSI =
new OBJECT_IDENTIFIER( new long[]{1, 2, 840, 113549} );
/**
* The OID space for RSA's PKCS (public key cryptography standards).
*/
public static final OBJECT_IDENTIFIER PKCS =
RSADSI.subBranch(1);
/**
* The OID space for RSA's PKCS #1.
*/
public static final OBJECT_IDENTIFIER PKCS1 =
PKCS.subBranch(1);
/**
* The OID space for RSA's PKCS #2, which has since been folded into
* PKCS #1.
*/
public static final OBJECT_IDENTIFIER PKCS2 =
PKCS.subBranch(2);
/**
* The OID space for RSA's message digest algorithms.
*/
public static final OBJECT_IDENTIFIER RSA_DIGEST = RSADSI.subBranch(2);
/**
* The OID space for RSA's password-based encryption standard.
*/
public static final OBJECT_IDENTIFIER PKCS5 = PKCS.subBranch(5);
/**
* The OID space for RSA's Selected Attribute Types standard, PKCS #9.
*/
public static final OBJECT_IDENTIFIER PKCS9 = PKCS.subBranch(9);
/**
* The OID space for RSA's personal information exchange syntax standard.
*/
public static final OBJECT_IDENTIFIER PKCS12 = PKCS.subBranch(12);
/**
* The OID space for RSA's ciphers.
*/
public static final OBJECT_IDENTIFIER RSA_CIPHER = RSADSI.subBranch(3);
/**
* The OID space for FIPS standardized algorithms.
*/
public static final OBJECT_IDENTIFIER ALGORITHM =
new OBJECT_IDENTIFIER( new long[] { 1, 3, 14, 3, 2 } );
/**
* The OID space for FIPS-180-2 SHA256/SHA384/SHA512 standardized algorithms.
*/
public static final OBJECT_IDENTIFIER HASH_ALGORITHM =
new OBJECT_IDENTIFIER( new long[] {2, 16, 840, 1, 101, 3, 4 } );
/**
* The OID space for PKIX.
*/
public static final OBJECT_IDENTIFIER PKIX =
new OBJECT_IDENTIFIER( new long[] { 1, 3, 6, 1, 5, 5, 7 } );
public static final OBJECT_IDENTIFIER
id_cmc = PKIX.subBranch( 7 );
/**
* CMC control attributes
*/
public static final OBJECT_IDENTIFIER
id_cmc_cMCStatusInfo = id_cmc.subBranch(1);
public static final OBJECT_IDENTIFIER
id_cmc_identification = id_cmc.subBranch(2);
public static final OBJECT_IDENTIFIER
id_cmc_identityProof = id_cmc.subBranch(3);
public static final OBJECT_IDENTIFIER
id_cmc_dataReturn = id_cmc.subBranch(4);
public static final OBJECT_IDENTIFIER
id_cmc_transactionId = id_cmc.subBranch(5);
public static final OBJECT_IDENTIFIER
id_cmc_senderNonce = id_cmc.subBranch(6);
public static final OBJECT_IDENTIFIER
id_cmc_recipientNonce = id_cmc.subBranch(7);
public static final OBJECT_IDENTIFIER
id_cmc_addExtensions = id_cmc.subBranch(8);
public static final OBJECT_IDENTIFIER
id_cmc_encryptedPOP = id_cmc.subBranch(9);
public static final OBJECT_IDENTIFIER
id_cmc_decryptedPOP = id_cmc.subBranch(10);
public static final OBJECT_IDENTIFIER
id_cmc_lraPOPWitness = id_cmc.subBranch(11);
public static final OBJECT_IDENTIFIER
id_cmc_getCert = id_cmc.subBranch(15);
public static final OBJECT_IDENTIFIER
id_cmc_getCRL = id_cmc.subBranch(16);
public static final OBJECT_IDENTIFIER
id_cmc_revokeRequest = id_cmc.subBranch(17);
public static final OBJECT_IDENTIFIER
id_cmc_regInfo = id_cmc.subBranch(18);
public static final OBJECT_IDENTIFIER
id_cmc_responseInfo = id_cmc.subBranch(19);
public static final OBJECT_IDENTIFIER
id_cmc_QueryPending = id_cmc.subBranch(21);
public static final OBJECT_IDENTIFIER
id_cmc_idPOPLinkRandom = id_cmc.subBranch(22);
public static final OBJECT_IDENTIFIER
id_cmc_idPOPLinkWitness = id_cmc.subBranch(23);
public static final OBJECT_IDENTIFIER
id_cmc_idConfirmCertAcceptance = id_cmc.subBranch(24);
public static final OBJECT_IDENTIFIER
id_cct = PKIX.subBranch( 12 );
public static final OBJECT_IDENTIFIER
id_cct_PKIData = id_cct.subBranch( 2 );
public static final OBJECT_IDENTIFIER
id_cct_PKIResponse = id_cct.subBranch( 3 );
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 6);
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
private long[] numbers;
/**
* Creates an OBJECT_IDENTIFIER from an array of longs, which constitute
* the numbers that make up the OBJECT IDENTIFIER.
*/
public OBJECT_IDENTIFIER( long[] numbers ) {
checkLongArray(numbers);
this.numbers = numbers;
}
/**
* Checks the given array of numbers to see if it is a valid OID.
* This is not an exhaustive test, it just looks for obvious problems.
* It will throw an assertion if a problem is found. With DEBUG turned
* off, it just checks for null.
*/
private static void checkLongArray(long[] numbers) {
Assert._assert(numbers != null);
if(numbers == null) {
throw new NullPointerException();
}
Assert._assert(numbers.length >= 2);
Assert._assert( numbers[0]==0 || numbers[0]==1 || numbers[0]==2 );
}
/**
* Creates an OBJECT_IDENTIFIER from a String version. The proper format
* for the OID string is dotted numbers, for example:
* "<code>3.2.456.53.23.64</code>".
*
* @exception NumberFormatException If the given string cannot be
* parsed into an OID.
*/
public OBJECT_IDENTIFIER( String dottedOID ) throws NumberFormatException {
if( dottedOID == null || dottedOID.length()==0 ) {
throw new NumberFormatException("OID string is zero-length");
}
StringTokenizer stok = new StringTokenizer(dottedOID, ".");
numbers = new long[ stok.countTokens() ];
int i = 0;
while(stok.hasMoreElements()) {
numbers[i++] = Long.parseLong( stok.nextToken() );
}
Assert._assert( i == numbers.length );
checkLongArray(numbers);
}
public long[] getNumbers() {
return numbers;
}
public int hashCode() {
int code = 1;
for(int i = 0; i < numbers.length; i++) {
code = (int) (code + numbers[i])*10;
}
return code;
}
/**
* Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one.
* For example, if <code>OBJECT_IDENTIFIER oid</code> has the value
* { 1 3 5 6 },
* then calling <code>oid.subBranch(4)</code> would return a new
* OBJECT_IDENTIFIER with the value { 1 3 5 6 4 }.
*/
public OBJECT_IDENTIFIER subBranch(long num) {
long[] nums = new long[ numbers.length + 1];
System.arraycopy(numbers, 0, nums, 0, numbers.length);
nums[numbers.length] = num;
return new OBJECT_IDENTIFIER(nums);
}
/**
* Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one.
* For example, if <code>OBJECT_IDENTIFIER oid</code> has the value
* { 1 3 5 6 },
* then calling <code>oid.subBranch(new long[]{ 4, 3})</code>
* would return a new
* OBJECT_IDENTIFIER with the value { 1 3 5 6 4 3}.
*/
public OBJECT_IDENTIFIER subBranch(long[] newNums) {
long[] nums = new long[ numbers.length + newNums.length];
System.arraycopy(numbers, 0, nums, 0, numbers.length);
System.arraycopy(newNums, 0, nums, numbers.length, newNums.length);
return new OBJECT_IDENTIFIER(nums);
}
public boolean equals(Object obj) {
if(obj == null || ! (obj instanceof OBJECT_IDENTIFIER)) {
return false;
}
long[] nums = ((OBJECT_IDENTIFIER)obj).numbers;
if( nums.length != numbers.length ) {
return false;
}
for(int i = 0; i < nums.length; i++) {
if( nums[i] != numbers[i] ) {
return false;
}
}
return true;
}
public String toString() {
String ret = "{" + String.valueOf(numbers[0]);
for(int i=1; i < numbers.length; i++) {
ret = ret + " " + numbers[i];
}
ret += "}";
return ret;
}
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
private byte[] encodedContents = null;
/**
* Gets the encoding of the contents, or a cached copy.
* Since the content encoding is the same regardless of the Tag,
* this only needs to be computed once.
*/
private byte[] getEncodedContents() {
if( encodedContents == null ) {
encodedContents = computeEncodedContents();
}
return encodedContents;
}
// We cache our encoding for a given tag. 99% of the time, only
// one tag will be used for an instance, so we will get a cache hit.
// In the remaining 1%, we'll have to recompute the encoding.
byte[] cachedEncoding=null;
Tag tagForCache=null;
/**
* Returns the encoding for the given tag. If the encoding for
* this tag was previously computed (and no encoding for a different
* tag has since been computed), this method returns a cached copy.
* Otherwise, the encoding will be recomputed.
*/
private byte[] getEncoding(Tag tag) {
if( ! tag.equals(tagForCache) ) {
// recompute for new tag
ByteArrayOutputStream out = new ByteArrayOutputStream();
ASN1Header head = getHeader(tag);
try {
head.encode(out);
} catch( IOException e ) {
// should never happen on a byte array output stream
Assert.notReached("exception while encoding ASN.1 header");
}
out.write( getEncodedContents(), 0, getEncodedContents().length );
tagForCache = tag;
cachedEncoding = out.toByteArray();
}
return cachedEncoding;
}
/**
* Compute the ASN1 header for this tag.
*/
private ASN1Header getHeader(Tag implicitTag) {
return new ASN1Header( implicitTag, FORM, getEncodedContents().length );
}
/**
* Actually computes the encoding of this object identifier.
*/
private byte[] computeEncodedContents() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
// handle first number
Assert._assert(numbers.length >= 2);
long n = numbers[0];
Assert._assert( n == 0 || n == 1 || n == 2 );
long outb = ( numbers[0] * 40 ) + numbers[1];
Assert._assert( ((byte)outb) == outb );
out.write( (byte)outb );
// handle consecutive numbers
for( int i = 2; i < numbers.length; i++ ) {
n = numbers[i];
Assert._assert( n >= 0 );
// array of output bytes, in reverse order. 10 bytes, at 7 bits
// per byte, is 70 bits, which is more than enough to handle
// the maximum value of a long, which takes up 63 bits.
byte[] rev = new byte[10];
int idx=0; // index into reversed bytes
// Create reversed byte list
do {
rev[idx++] = (byte) (n % 128);
n = n / 128;
} while( n > 0 );
idx--; // backup to point to last element
// now print them in reverse order
while( idx > 0 ) {
// all but last byte have MSB==1
out.write( rev[idx--] | 0x80 );
}
Assert._assert(idx == 0);
// last byte has MSB==0
out.write( rev[0] );
}
return out.toByteArray();
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
ostream.write( getEncoding(implicitTag) );
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
///////////////////////////////////////////////////////////////////////
// OBJECT_IDENTIFIER.Template
//
public static class Template implements ASN1Template {
public Tag getTag() {
return OBJECT_IDENTIFIER.TAG;
}
public boolean tagMatch(Tag tag) {
return( tag.equals(OBJECT_IDENTIFIER.TAG) );
}
public Form getForm() {
return OBJECT_IDENTIFIER.FORM;
}
public boolean formMatch(Form form) {
return( form == OBJECT_IDENTIFIER.FORM );
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(getTag(), istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header(istream);
long remainingContent = head.getContentLength();
// Check the information gleaned from the header
if( ! head.getTag().equals( implicitTag ) ) {
throw new InvalidBERException("Incorrect tag for "+
"OBJECT IDENTIFIER: "+ head.getTag() );
}
if( head.getForm() != getForm() ) {
throw new InvalidBERException("Incorrect form for OBJECT "+
"IDENTIFIER");
}
if( remainingContent < 1 ) {
throw new InvalidBERException("Invalid 0 length for OBJECT"+
" IDENTIFIER");
}
Vector numberV = new Vector();
// handle first byte, which contains first two numbers
byte b = readByte(istream);
remainingContent--;
long num = b % 40;
numberV.addElement( new Long( b % 40 ) ); // second number
numberV.insertElementAt( new Long( b / 40 ), 0); // first number
// handle the rest of the numbers
while( remainingContent > 0 ) {
num = 0;
// keep reading until MSB == 0
int bitcount=0;
do {
if( (bitcount+=7) > 63 ) {
// we're about to overflow our long
throw new InvalidBERException("OBJECT IDENTIFIER "+
"element too long; max is 63 bits");
}
b = readByte(istream);
remainingContent--;
num <<= 7;
num |= (b & 0x7f);
} while( (b & 0x80) != 0 );
numberV.addElement( new Long( num ) );
}
// convert Vector to array
long numbers[] = new long[ numberV.size() ];
for(int i = 0; i < numbers.length; i++) {
numbers[i] = ((Long)numberV.elementAt(i)).longValue();
}
// create OBJECT_IDENTIFIER from array
return new OBJECT_IDENTIFIER(numbers);
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "OBJECT IDENTIFIER");
}
}
/**
* Reads in a byte from the stream, throws an InvalidBERException
* if EOF is reached.
*/
private static byte readByte(InputStream istream)
throws InvalidBERException, IOException
{
int n = istream.read();
if( n == -1 ) {
throw new InvalidBERException("End-of-file reached while "+
"decoding OBJECT IDENTIFIER");
}
Assert._assert( (n & 0xff) == n );
return (byte) n;
}
} // end of OBJECT_IDENTIFIER.Template
}

View File

@@ -1,150 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
public class OCTET_STRING implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 4);
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
byte[] data;
private OCTET_STRING() { }
public OCTET_STRING( byte[] data ) {
this.data = data;
}
public byte[] toByteArray() {
return data;
}
public void encode(OutputStream ostream) throws IOException {
// use getTag() so we can be subclassed
encode(getTag(), ostream);
}
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
ASN1Header head = new ASN1Header(implicitTag, FORM, data.length);
head.encode(ostream);
ostream.write(data);
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
public static class Template implements ASN1Template {
public Tag getTag() {
return TAG;
}
public boolean tagMatch(Tag tag) {
return( TAG.equals(tag) );
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(getTag(), istream);
}
// this can be overridden by subclasses
protected ASN1Value generateInstance(byte[] bytes) {
return new OCTET_STRING( bytes );
}
// this can be overridden by subclasses
protected String getName() {
return "OCTET_STRING";
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag);
byte[] data;
if( head.getContentLength() == -1 ) {
// indefinite length encoding
ASN1Header ahead;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
do {
ahead = ASN1Header.lookAhead( istream );
if( ! ahead.isEOC() ) {
OCTET_STRING.Template ot = new OCTET_STRING.Template();
OCTET_STRING os = (OCTET_STRING) ot.decode(istream);
bos.write( os.toByteArray() );
}
} while( ! ahead.isEOC() );
// consume EOC
ahead = new ASN1Header(istream);
data = bos.toByteArray();
} else {
data = new byte[ (int) head.getContentLength() ];
ASN1Util.readFully(data, istream);
}
return generateInstance(data);
} catch( InvalidBERException e ) {
throw new InvalidBERException(e, getName());
}
}
} // end of Template
}

View File

@@ -1,160 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
public class PrintableString extends CharacterString implements ASN1Value {
public PrintableString(char[] chars) throws CharConversionException {
super(chars);
}
public PrintableString(String s) throws CharConversionException {
super(s);
}
CharConverter getCharConverter() {
return new PrintableConverter();
}
public static final Tag TAG = new Tag( Tag.UNIVERSAL, 19 );
public static final Form FORM = Form.PRIMITIVE;
public Tag getTag() {
return TAG;
}
/**
* Returns a singleton instance of the decoding template for this class.
*/
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template implements ASN1Template
{
protected Tag getTag() {
return TAG;
}
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
protected CharConverter getCharConverter() {
return new PrintableConverter();
}
protected CharacterString generateInstance(char[] chars)
throws CharConversionException
{
return new PrintableString(chars);
}
protected String typeName() {
return "PrintableString";
}
}
private static class PrintableConverter implements CharConverter {
private static boolean[] isPrintable = new boolean[128];
static {
char b;
for(b='A'; b <= 'Z'; b++) {
isPrintable[b] = true;
}
for(b='a'; b <= 'z'; b++) {
isPrintable[b] = true;
}
for(b='0'; b <= '9'; b++) {
isPrintable[b] = true;
}
isPrintable[' '] = true;
isPrintable['\''] = true;
isPrintable['('] = true;
isPrintable[')'] = true;
isPrintable['+'] = true;
isPrintable[','] = true;
isPrintable['-'] = true;
isPrintable['.'] = true;
isPrintable['/'] = true;
isPrintable[':'] = true;
isPrintable['='] = true;
isPrintable['?'] = true;
}
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException
{
char[] chars = new char[len];
int c; // char index
int b; // byte index
for(c=0, b=offset; c < len; b++, c++) {
if( (bytes[b] & 0x80) != 0 || !isPrintable[bytes[b]] ) {
/* fix for bug 359010 - don't throw, just skip
* throw new CharConversionException(bytes[b]+ " is not "+
* "a valid character for a PrintableString");
*/
} else {
chars[c] = (char) bytes[b];
}
}
return chars;
}
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException
{
byte[] bytes = new byte[len];
int c; // char index
int b; // byte index
for(c=0, b=0; b < len; b++, c++) {
if( (chars[c] & 0xff80) != 0 || !isPrintable[chars[c]] ) {
throw new CharConversionException(chars[c]+ " is not "+
"a valid character for a PrintableString");
}
bytes[b] = (byte) (chars[c] & 0x7f);
}
return bytes;
}
} // end of char converter
}

View File

@@ -1,762 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.util.Vector;
import org.mozilla.jss.util.Assert;
import java.math.BigInteger;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/**
* An ASN.1 SEQUENCE. This class is an ordered collection of ASN.1 values.
* It has an interface similar to a Java <code>Vector</code>.
* Null entries may be added; they will be skipped when encoded.
*/
public class SEQUENCE extends SET implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 16);
public Tag getTag() {
return TAG;
}
public static Template getTemplate() {
return new Template();
}
/**
* Writes the DER encoding to the given output stream,
* using the given implicit tag.
*/
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
BERencode(implicitTag, ostream);
}
// SET.Element and SEQUENCE.Element are identical types. We could
// have just reused SET.Element, but that would have been a bit
// confusing for users.
private static class Element extends SET.Element {
public Element( ASN1Value val ) {
super(val);
}
public Element( Tag implicitTag, ASN1Value val) {
super(implicitTag, val);
}
}
/**
* A class for constructing a <code>SEQUENCE</code> from its BER encoding.
* It is an ordered collection of sub-templates. Each sub-template can be
* marked optional, or a default value can be given.
*/
public static class Template implements ASN1Template {
private Vector elements = new Vector();
private void addElement(Element el) {
elements.addElement( el );
}
private void insertElementAt(Element e, int index) {
elements.insertElementAt(e, index);
}
/**
* Adds a sub-template to the end of this SEQUENCE template. For example,
* if the ASN.1 included:
* <pre>
* MySequence ::= SEQUENCE {
* item SubType,
* ... }
* </pre>
* the "item" element would be added to the MySequence template with:
* <pre>
* mySequence.addElement( new SubType.Template() );
* </pre>
*/
public void addElement( ASN1Template t ) {
addElement( new Element(null, t, false) );
}
/**
* Inserts the template at the given index.
*/
public void insertElementAt( ASN1Template t, int index )
{
insertElementAt( new Element(null, t, false), index );
}
/**
* Adds a sub-template to the end of this SEQUENCE template, with the
* given implicit tag. For example, if the ASN.1 were:
* <pre>
* MySequence ::= SEQUENCE {
* item [0] IMPLICIT SubType,
* ... }
* </pre>
* the "item" element would be added to the MySequence template with:
* <pre>
* mySequence.addElement( new Tag(0), new SubType.Template());
* </pre>
*/
public void addElement( Tag implicitTag, ASN1Template t ) {
addElement( new Element(implicitTag, t, false) );
}
/**
* Inserts the template with the given implicit tag at the given index.
*/
public void insertElementAt( Tag implicit, ASN1Template t,
int index )
{
insertElementAt( new Element(implicit, t, false), index );
}
/**
* Adds an optional sub-template. For example, if the ASN.1 were:
* <pre>
* MySequence ::= SEQUENCE {
* item SubType OPTIONAL,
* ... }
* </pre>
* the "item" element would be added to the MySequence template with:
* <pre>
* mySequence.addOptionalElement( new SubType.Template() );
* </pre>
*/
public void addOptionalElement( ASN1Template t ) {
addElement( new Element(null, t, true) );
}
/**
* Inserts the optional template at the given index.
*/
public void insertOptionalElementAt( ASN1Template t, int index )
{
insertElementAt( new Element(null, t, true), index );
}
/**
* Adds an optional sub-template with an implicit tag. For example,
* if the ASN.1 were:
* <pre>
* MySequence ::= SEQUENCE {
* item [0] IMPLICIT SubType OPTIONAL,
* ... }
* </pre>
* the "item" element would be added to the MySequence template with:
* <pre>
* mySequence.addOptionalElement( new SubType.Template() );
* </pre>
*/
public void addOptionalElement( Tag implicitTag, ASN1Template t ) {
addElement( new Element(implicitTag, t, true) );
}
/**
* Inserts the optional template with the given default
* value at the given index.
*/
public void insertOptionalElementAt( Tag implicit, ASN1Template t,
int index )
{
insertElementAt( new Element(implicit, t, true), index );
}
/**
* Adds a sub-template with a default value. For example,
* if the ASN.1 were:
* <pre>
* MySequence ::= SEQUENCE {
* version INTEGER DEFAULT 1,
* ... }
* </pre>
* the "item" element would be added to the MySequence template with:
* <pre>
* mySequence.addElement( new INTEGER.Template(), new INTEGER(1) );
* </pre>
* @param def The default value for this field, which will be used if
* no value is supplied by the encoded structure. It must be of
* the same type as what the template would produce.
*/
public void addElement( ASN1Template t, ASN1Value def ) {
addElement( new Element(null, t, def) );
}
/**
* Inserts the template with the given default
* value at the given index.
*/
public void insertElementAt( ASN1Template t, ASN1Value def, int index )
{
insertElementAt( new Element(null, t, def), index );
}
/**
* Adds a sub-template with a default value and an implicit tag.
* For example, if the ASN.1 were:
* <pre>
* MySequence ::= SEQUENCE {
* version [0] IMPLICIT INTEGER DEFAULT 1,
* ... }
* </pre>
* the "item" element would be added to the MySequence template with:
* <pre>
* mySequence.addElement( new Tag(0), new INTEGER.Template(),
* new INTEGER(1) );
* </pre>
* @param def The default value for this field, which will be used if
* no value is supplied by the encoded structure. It must be of
* the same type as what the template would produce.
*/
public void addElement( Tag implicitTag, ASN1Template t, ASN1Value def) {
addElement( new Element(implicitTag, t, def) );
}
/**
* Inserts the template with the given implicit tag and given default
* value at the given index.
*/
public void insertElementAt( Tag implicit, ASN1Template t, ASN1Value def,
int index )
{
insertElementAt( new Element(implicit, t, def), index );
}
/**
* Returns the implicit tag of the item stored at the given index.
* May be NULL if no implicit tag was specified.
*/
public Tag implicitTagAt( int index ) {
return ((Element)elements.elementAt(index)).getImplicitTag();
}
/**
* Returns the sub-template stored at the given index.
*/
public ASN1Template templateAt( int index ) {
return ((Element)elements.elementAt(index)).getTemplate();
}
/**
* Returns whether the sub-template at the given index is optional.
*/
public boolean isOptionalAt( int index ) {
return ((Element)elements.elementAt(index)).isOptional();
}
/**
* Returns the default value for the sub-template at the given index.
* May return NULL if no default value was specified.
*/
public ASN1Value defaultAt( int index ) {
return ((Element)elements.elementAt(index)).getDefault();
}
/**
* Returns the number of elements in this SEQUENCE template.
*/
public int size() {
return elements.size();
}
/**
* Removes all sub-templates from this SEQUENCE template.
*/
public void removeAllElements() {
elements.removeAllElements();
}
/**
* Removes the sub-template at the given index.
*/
public void removeElementAt(int index) {
elements.removeElementAt(index);
}
Tag getTag() {
return SEQUENCE.TAG;
}
public boolean tagMatch(Tag tag) {
return( tag.equals(SEQUENCE.TAG) );
}
/**
* Decodes a SEQUENCE from its BER encoding.
*/
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(getTag(), istream);
}
/**
* Decodes a SEQUENCE from its BER encoding, where the SEQUENCE itself has
* an implicit tag.
*/
public ASN1Value decode(Tag tag, InputStream istream)
throws IOException, InvalidBERException
{
int index = 0;
try {
ASN1Header header = new ASN1Header(istream);
header.validate( tag, Form.CONSTRUCTED );
// will be -1 for indefinite encoding
long remainingContent = header.getContentLength();
boolean repeatableElement=false;
SEQUENCE seq = new SEQUENCE();
ASN1Header lookAhead=null;
// go through the whole template
for( index = 0; index < size(); index++ ) {
// find out about the next item
if( remainingContent == 0 ) {
lookAhead = null;
} else {
// remainingContent > 0 or remainingContent == -1, which means
// indefinite encoding.
lookAhead = ASN1Header.lookAhead(istream);
}
// skip over items that don't match. Hopefully they are
// optional or have a default. Otherwise, it's an error.
Element e = (Element) elements.elementAt(index);
if( (lookAhead == null) || lookAhead.isEOC() ||
! e.tagMatch( lookAhead.getTag() ) )
{
if( e.isRepeatable() ) {
repeatableElement = true;
} else if( e.isOptional() ) {
// put an empty entry into the SEQUENCE
SEQUENCE.Element se = new SEQUENCE.Element(null, null );
seq.addElement( null );
} else if( e.getDefault() != null ) {
// use the default
seq.addElement( e.getDefault() );
} else {
String tagDesc;
if( lookAhead == null ) {
tagDesc = "(null)";
} else {
tagDesc = lookAhead.getTag().toString();
}
throw new InvalidBERException("Missing item #" + index +
": found " + tagDesc );
}
continue;
}
// Decode this element
ASN1Template t = e.getTemplate();
ASN1Value val;
CountingStream countstream = new CountingStream(istream);
if( e.getImplicitTag() == null ) {
val = t.decode(countstream);
} else {
val = t.decode(e.getImplicitTag(), countstream);
}
// Decrement remaining count
long len = countstream.getNumRead();
if( remainingContent != -1 ) {
if( remainingContent < len ) {
// this item went past the end of the SEQUENCE
throw new InvalidBERException("Item went "+
(len-remainingContent)+" bytes past the end of"+
" the SEQUENCE");
}
remainingContent -= len;
}
// Store this element in the SEQUENCE
if( e.producesOutput() ) {
if( e.getImplicitTag() == null ) {
// no implicit tag
seq.addElement( val );
} else {
// there is an implicit tag
seq.addElement( e.getImplicitTag(), val );
}
}
// If this element is repeatable, don't go on to the next element
if( e.isRepeatable() ) {
repeatableElement = true;
index--;
}
}
if( remainingContent > 0 ) {
throw new InvalidBERException("SEQUENCE is " + remainingContent +
" bytes longer than expected");
}
Assert._assert( remainingContent == 0 || remainingContent == -1 );
// If this was indefinite-length encoding, consume the end-of-contents
if( remainingContent == -1 ) {
lookAhead = new ASN1Header(istream);
if( ! lookAhead.isEOC() ) {
throw new InvalidBERException("No end-of-contents marker");
}
}
// Make sure we stayed in sync
if( ! repeatableElement ) {
Assert._assert(index == seq.size());
}
return seq;
} catch(InvalidBERException e) {
e.append("SEQUENCE(item #" +index + ")");
throw e;
}
}
/**
* An element of a SEQUENCE template. For each sub-template, contains the
* template, its optionality, its implicit tag, and its default value.
*/
static class Element {
/**
* Creates a new element, which may or may not be optional.
*/
public Element(Tag implicitTag, ASN1Template type, boolean optional)
{
this(implicitTag, type, optional, true);
}
/**
* Creates a new element, which may or may not be optional.
*/
public Element(Tag implicitTag, ASN1Template type, boolean optional,
boolean doesProduceOutput)
{
this.type = type;
defaultVal = null;
this.optional = optional;
this.implicitTag = implicitTag;
this.doesProduceOutput = doesProduceOutput;
}
/**
* Creates a new element with a default value.
*/
public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal)
{
this.type = type;
this.defaultVal = defaultVal;
optional = false;
this.implicitTag = implicitTag;
}
private boolean doesProduceOutput = true;
boolean producesOutput() {
return doesProduceOutput;
}
// repeatability is provided to allow for SEQUENCE OF SIZE
// constructs. It is package private.
private boolean repeatable;
void makeRepeatable() {
repeatable = true;
}
boolean isRepeatable() {
return repeatable;
}
private boolean optional;
public boolean isOptional() {
return optional;
}
private Tag implicitTag=null;
public Tag getImplicitTag() {
return implicitTag;
}
public boolean tagMatch(Tag tag) {
if( implicitTag != null ) {
return( implicitTag.equals(tag) );
} else {
return type.tagMatch(tag);
}
}
private ASN1Template type;
public ASN1Template getTemplate() {
return type;
}
private ASN1Value defaultVal=null;
public ASN1Value getDefault() {
return defaultVal;
}
}
} // End of SEQUENCE.Template
/**
* A Template for decoding SEQUENCE OF values. The main difference between
* a SEQUENCE.Template and a SEQUENCE.OF_Template is that a regular template
* specifies the exact ordering, number, and type of elements of the sequence,
* while
* an OF_Template has an indefinite number of elements, all the same type.
* For example, given:
* <pre>
* MyType ::= SEQUENCE OF Extension
* </pre>
* a MyType could be decoded with:
* <pre>
* SEQUENCE.OF_Template myTypeTemplate = new SEQUENCE.OF_Template( new
* Extension.Template) );
* SEQUENCE seq = (SEQUENCE) myTypeTemplate.decode(someInputStream);
* </pre>
* The number of <code>Extension</code>s actually decoded could be found
* with <code>seq.size()</code>.
*/
public static class OF_Template implements ASN1Template {
private OF_Template() { }
Template template; // a normal SEQUENCE template
public OF_Template(ASN1Template type) {
template = new Template();
Template.Element el = new Template.Element(null, type, true); //optional
el.makeRepeatable();
template.addElement( el );
}
public static OF_Template makeOutputlessOFTemplate(ASN1Template type) {
OF_Template t = new OF_Template();
t.template = new Template();
Template.Element el = new Template.Element(null, type, true, false);
el.makeRepeatable();
t.template.addElement(el);
return t;
}
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
/**
* Decodes a SEQUENCE OF from an input stream.
*/
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return template.decode(istream);
}
/**
* Decodes a SEQUENCE OF with an implicit tag from an input stream.
*/
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
return template.decode(implicitTag, istream);
}
}
public static void main(String args[]) {
try {
if(args.length > 0) {
// input
Template type = new Template();
type.addOptionalElement( new Tag(15), new INTEGER.Template() );
type.addElement( new Tag(16), new INTEGER.Template(),
new INTEGER(42) );
type.addElement( new INTEGER.Template() );
type.addElement( new BOOLEAN.Template() );
type.addElement( new INTEGER.Template() );
type.addOptionalElement( new Tag(12), new INTEGER.Template() );
type.addElement( new BOOLEAN.Template() );
type.addElement( new Tag(13), new INTEGER.Template(),
new INTEGER(53) );
type.addElement( new INTEGER.Template() );
type.addElement( new INTEGER.Template() );
type.addOptionalElement( new Tag(14), new INTEGER.Template() );
type.addElement( new OBJECT_IDENTIFIER.Template() );
type.addElement( new NULL.Template() );
type.addElement( new EXPLICIT.Template(
new Tag(27), new INTEGER.Template()));
type.addElement( new ENUMERATED.Template() );
type.addElement( new OCTET_STRING.Template() );
type.addElement( new IA5String.Template() );
CHOICE.Template choice = new CHOICE.Template();
choice.addElement( new Tag(23), new INTEGER.Template() );
choice.addElement( new BOOLEAN.Template() );
type.addElement( choice );
type.addElement( new BIT_STRING.Template() );
type.addElement( new ANY.Template() );
type.addElement( new PrintableString.Template() );
type.addElement( new OF_Template( new INTEGER.Template() ) );
type.addElement( new OF_Template( new INTEGER.Template() ) );
FileInputStream fin = new FileInputStream(args[0]);
System.out.println("Available: "+fin.available());
byte[] stuff = new byte[ fin.available() ];
ASN1Util.readFully(stuff, fin);
SEQUENCE s=null;
for( int i = 0; i < 1; i++) {
s = (SEQUENCE) type.decode( new ByteArrayInputStream(stuff) );
}
for(int i=0; i < s.size(); i ++ ) {
ASN1Value v = s.elementAt(i);
if(v instanceof ENUMERATED) {
ENUMERATED en = (ENUMERATED) v;
System.out.println("ENUMERATED: "+en);
} else if( v instanceof INTEGER ) {
INTEGER in = (INTEGER) v;
System.out.println("INTEGER: "+in);
} else if(v instanceof BOOLEAN ) {
BOOLEAN bo = (BOOLEAN) v;
System.out.println("BOOLEAN: "+bo);
} else if(v instanceof OBJECT_IDENTIFIER) {
OBJECT_IDENTIFIER oid = (OBJECT_IDENTIFIER) v;
System.out.println("OID: "+oid);
} else if(v instanceof NULL) {
NULL n = (NULL) v;
System.out.println("NULL");
} else if(v instanceof EXPLICIT) {
EXPLICIT ex = (EXPLICIT) v;
INTEGER in = (INTEGER) ex.getContent();
System.out.println("EXPLICIT ["+ex.getTag()+"]: "+
"INTEGER: "+in);
} else if(v instanceof OCTET_STRING) {
OCTET_STRING os = (OCTET_STRING) v;
byte[] bytes = os.toByteArray();
System.out.print("OCTET_STRING: ");
for(int j = 0; j < bytes.length; j++) {
System.out.print(bytes[j]+" ");
}
System.out.println("");
} else if( v instanceof CharacterString ) {
CharacterString cs = (CharacterString) v;
System.out.println("String: "+cs);
} else if( v instanceof BIT_STRING ) {
BIT_STRING bs = (BIT_STRING) v;
System.out.print("BIT_STRING: padCount="+
bs.getPadCount()+" : ");
byte[] bits = bs.getBits();
for(int j = 0; j < bits.length; j++) {
System.out.print(bits[j]+" ");
}
System.out.println("");
} else if( v instanceof ANY ) {
ANY any = (ANY) v;
Tag tag = any.getTag();
System.out.println("Got ANY, tag is "+tag);
ByteArrayInputStream bos =
new ByteArrayInputStream( any.getEncoded() );
INTEGER in = (INTEGER) new INTEGER.Template().decode(bos);
System.out.println(" INTEGER: "+in);
} else if(v instanceof SEQUENCE ) {
SEQUENCE seq = (SEQUENCE)v;
System.out.println("SEQUENCE: ");
for(int j=0; j < seq.size(); j++ ) {
INTEGER in = (INTEGER) seq.elementAt(j);
System.out.println(" INTEGER: "+in);
}
} else {
System.out.println("Unknown value");
}
}
} else {
// output
SEQUENCE seq = new SEQUENCE();
seq.addElement( new INTEGER(5) );
seq.addElement( new BOOLEAN(true) );
seq.addElement( new INTEGER(-322) );
seq.addElement( new BOOLEAN(false) );
seq.addElement( new INTEGER(0) );
seq.addElement( new INTEGER("2934293834242") );
seq.addElement( new OBJECT_IDENTIFIER(
new long[] { 1, 2, 127, 563, 1231982 } ) );
seq.addElement( new NULL() );
seq.addElement( new EXPLICIT( new Tag(27), new INTEGER(39) ));
seq.addElement( new ENUMERATED(983) );
seq.addElement( new OCTET_STRING( new byte[] {
(byte)0x0, (byte)0xff, (byte)0xcc} ) );
seq.addElement( new IA5String("foobar") );
seq.addElement( new Tag(23), new INTEGER(234) );
//seq.addElement( new BOOLEAN(false) );
byte[] bits = new byte[]{ (byte)0x80, (byte)0xff, (byte)0x0f };
seq.addElement( new BIT_STRING( bits, 3 ) );
seq.addElement( new INTEGER(82734) );
seq.addElement( new PrintableString("I'm printable??") );
SEQUENCE nested = new SEQUENCE();
nested.addElement( new INTEGER( 5 ) );
nested.addElement( new INTEGER( 6 ) );
seq.addElement( nested );
nested = new SEQUENCE();
seq.addElement( nested );
seq.encode(System.out);
System.out.flush();
}
} catch( Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,933 +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 Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* 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 ***** */
package org.mozilla.jss.asn1;
import java.math.BigInteger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import org.mozilla.jss.util.Assert;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
/**
* An ASN.1 SET, which is an unordered collection of ASN.1 values.
* It has an interface like a Java Vector, but the ordering is arbitrary.
* Null entries may be added; they will be skipped when encoding.
*/
public class SET implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 17);
public Tag getTag() {
return TAG;
}
protected static final Form FORM = Form.CONSTRUCTED;
// The elements of the set
protected Vector elements = new Vector();
private void addElement( Element e ) {
elements.addElement(e);
}
private void insertElementAt( Element e, int index ) {
elements.insertElementAt(e, index);
}
/**
* Adds an element to this SET.
*/
public void addElement( ASN1Value v ) {
addElement( new Element(v) );
}
/**
* Adds an element to this SET with the given implicit tag. For example,
* if the ASN.1 were:
* <pre>
* MyType ::= SET {
* item [0] IMPLICIT INTEGER,
* ... }
* </pre>
* then the "item" element could be added (with a sample value of 45)
* to the SET with:
* <pre>
* myTypeInstance.addElement( new Tag(0), new INTEGER(45) );
* </pre>
*/
public void addElement( Tag implicitTag, ASN1Value v ) {
addElement( new Element(implicitTag, v) );
}
/**
* Inserts an element at the given index.
*/
public void insertElementAt( ASN1Value v, int index ) {
insertElementAt( new Element(v), index );
}
/**
* Inserts an element with the given implicit tag at the given index.
*/
public void insertElementAt( Tag implicitTag, ASN1Value v, int index ) {
insertElementAt( new Element(implicitTag, v), index );
}
/**
* Returns the element at the given index in the SET.
*/
public ASN1Value elementAt( int index ) {
return ((Element)elements.elementAt(index)).getValue();
}
/**
* Returns the tag of the element at the given index. If the element
* has an implicit tag, that is returned. Otherwise, the tag of the
* underlying type is returned.
*/
public Tag tagAt( int index ) {
Tag implicit = ((Element)elements.elementAt(index)).getImplicitTag();
if( implicit != null ) {
return implicit;
} else {
return elementAt(index).getTag();
}
}
/**
* Returns the element with the given Tag, or null if no element exists
* with the given tag.
*/
public ASN1Value elementWithTag( Tag tag ) {
// hmmm...linear search for now, should use hashtable later
int size = elements.size();
for( int i=0; i < size; i++ ) {
Element e = (Element) elements.elementAt(i);
if( e.getTag().equals(tag) ) {
return e.getValue();
}
}
return null;
}
/**
* Returns the number of elements in this SET.
*/
public int size() {
return elements.size();
}
/**
* Removes all elements from this SET.
*/
public void removeAllElements() {
elements.removeAllElements();
}
/**
* Removes the element from the specified index.
*/
public void removeElementAt(int index) {
elements.removeElementAt(index);
}
/**
* Writes the DER encoding to the given output stream.
*/
public void encode(OutputStream ostream)
throws IOException
{
encode(getTag(), ostream);
}
/**
* Writes the DER encoding to the given output stream,
* using the given implicit tag. To satisfy DER encoding rules,
* the elements will be re-ordered either by tag or lexicographically.
*/
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
// what ordering method?
boolean lexOrdering;
if( elements.size() < 2 ) {
// doesn't matter, only one element
lexOrdering = true;
} else if( tagAt(0).equals(tagAt(1)) ) {
// tags are the same, lexicographic ordering
lexOrdering = true;
} else {
// tags are different, order by tag
lexOrdering = false;
}
// compute and order contents
int numElements = elements.size();
int totalBytes = 0;
Vector encodings = new Vector(numElements);
Vector tags = new Vector(numElements);
int i;
for(i = 0; i < numElements; i++ ) {
// if an entry is null, just skip it
if( elementAt(i) != null ) {
byte[] enc = ASN1Util.encode(tagAt(i), elementAt(i));
totalBytes += enc.length;
if( lexOrdering ) {
insertInOrder(encodings, enc);
} else {
insertInOrder(encodings, enc, tags, (int) tagAt(i).getNum());
}
}
}
// write header
ASN1Header header = new ASN1Header( implicitTag, FORM, totalBytes );
header.encode(ostream);
// write contents in order
for(i=0; i < numElements; i++ ) {
ostream.write( (byte[]) encodings.elementAt(i) );
}
}
/**
* Encodes this SET without re-ordering it. This may violate
* DER, but it is within BER.
*/
public void BERencode(Tag implicitTag, OutputStream ostream)
throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// compute contents
int size = elements.size();
for(int i = 0; i < size; i++ ) {
ASN1Value el = elementAt(i);
if(el!=null) {
el.encode(tagAt(i), bos);
}
}
byte[] bytes = bos.toByteArray();
// write header
ASN1Header header = new ASN1Header( implicitTag, FORM, bytes.length );
header.encode(ostream);
// write contents
ostream.write(bytes);
}
// performs ascending lexicographic ordering
// linear search, but number of items is usually going to be small.
private static void insertInOrder(Vector encs, byte[] enc) {
int size = encs.size();
// find the lowest item that we are less than or equal to
int i;
for(i=0; i < size; i++) {
if( compare(enc, (byte[])encs.elementAt(i)) < 1 ) {
break;
}
}
// insert ourself before this item
encs.insertElementAt(enc, i);
}
// performs ascending ordering by tag
// linear search, but number of items is usually going to be small.
private static void insertInOrder(Vector encs, byte[] enc, Vector tags,
int tag)
{
int size = encs.size();
// find the lowest item that we are less than or equal to
int i;
for(i = 0; i < size; i++) {
if( tag <= ((Integer)tags.elementAt(i)).intValue() ) {
break;
}
}
// insert ourself before this item
encs.insertElementAt(enc, i);
tags.insertElementAt(new Integer(i), i );
}
// compares two byte arrays
// returns 1 if left > right, -1 if left < right, 0 if left == right
private static int compare(byte[] left, byte[] right) {
int min = (left.length < right.length) ? left.length : right.length;
for(int i=0; i < min; i++) {
if( (left[i]&0xff) < (right[i]&0xff) ) {
return -1;
} else if( (left[i]&0xff) > (right[i]&0xff) ) {
return 1;
}
}
// equal up to the minimal endpoint
if( left.length > min ) {
Assert._assert(right.length==min);
return 1;
}
if( right.length > min ) {
Assert._assert(left.length==min);
return -1;
}
return 0;
}
/**
* An element of a SET
*/
static class Element {
/**
* Makes a new SET element from the given value.
*/
public Element( ASN1Value val ) {
this.val = val;
}
/**
* Makes a new SET element from the given value with the given
* implicit tag.
*/
public Element( Tag implicitTag, ASN1Value val )
{
this.val = val;
this.implicitTag = implicitTag;
}
private ASN1Value val;
/**
* Returns the value of this SET element.
*/
public ASN1Value getValue() {
return val;
}
/**
* Returns the tag that actually shows up in the encoding.
* If there is an implicit tag, it will be used. Otherwise,
* it will be the base tag for the value.
*/
public Tag getTag() {
if(implicitTag!=null) {
return implicitTag;
} else {
return val.getTag();
}
}
private Tag implicitTag=null;
/**
* Returns the implicit tag for this value, if there is one.
* If not, returns null.
*/
public Tag getImplicitTag() {
return implicitTag;
}
}
/**
* SET.Template
* This class is used for decoding DER-encoded SETs.
*/
public static class Template implements ASN1Template {
private Vector elements = new Vector();
private void addElement( Element e ) {
elements.addElement(e);
}
private void insertElementAt( Element e, int index ) {
elements.insertElementAt(e, index);
}
/**
* Adds a sub-template to the end of this SET template. For example,
* if the ASN.1 included:
* <pre>
* MySet ::= SET {
* item SubType,
* ... }
* </pre>
* the "item" element would be added to the MySet template with:
* <pre>
* mySet.addElement( new SubType.Template() );
* </pre>
*/
public void addElement( ASN1Template t ) {
addElement( new Element(TAG, t, false) );
}
/**
* Inserts the template at the given index.
*/
public void insertElementAt( ASN1Template t, int index )
{
insertElementAt( new Element(TAG, t, false), index );
}
/**
* Adds a sub-template with the given implicit tag to the end of this
* SET template. For example, if the ASN.1 included:
* <pre>
* MySet ::= SET {
* item [0] IMPLICIT SubType,
* ... }
* </pre>
* the "item" element would be added to the MySet template with:
* <pre>
* mySet.addElement( new Tag(0), new SubType.Template() );
* </pre>
*/
public void addElement( Tag implicit, ASN1Template t ) {
addElement( new Element(implicit, t, false) );
}
/**
* Inserts the template with the given implicit tag at the given index.
*/
public void insertElementAt( Tag implicit, ASN1Template t,
int index )
{
insertElementAt( new Element(implicit, t, false), index );
}
/**
* Adds an optional sub-template to the end
* of this SET template. For example, if the ASN.1 included:
* <pre>
* MySet ::= SET {
* item SubType OPTIONAL,
* ... }
* </pre>
* the "item" element would be added to the MySet template with:
* <pre>
* mySet.addOptionalElement( new SubType.Template() );
* </pre>
*/
public void addOptionalElement( ASN1Template t ) {
addElement( new Element(TAG, t, true) );
}
/**
* Inserts the optional template at the given index.
*/
public void insertOptionalElementAt( ASN1Template t, int index )
{
insertElementAt( new Element(null, t, true), index );
}
/**
* Adds an optional sub-template with the given implicit tag to the end
* of this SET template. For example, if the ASN.1 included:
* <pre>
* MySet ::= SET {
* item [0] IMPLICIT SubType OPTIONAL,
* ... }
* </pre>
* the "item" element would be added to the MySet template with:
* <pre>
* mySet.addOptionalElement( new Tag(0), new SubType.Template() );
* </pre>
*/
public void addOptionalElement( Tag implicit, ASN1Template t ) {
addElement( new Element(implicit, t, true) );
}
/**
* Inserts the optional template with the given default
* value at the given index.
*/
public void insertOptionalElementAt( Tag implicit, ASN1Template t,
int index )
{
insertElementAt( new Element(implicit, t, true), index );
}
/**
* Adds a sub-template with the given default value to the end
* of this SET template. For example, if the ASN.1 included:
* <pre>
* MySet ::= SET {
* item INTEGER DEFAULT (5),
* ... }
* </pre>
* the "item" element would be added to the MySet template with:
* <pre>
* mySet.addElement( new SubType.Template(), new INTEGER(5) );
* </pre>
*/
public void addElement( ASN1Template t, ASN1Value def ) {
addElement( new Element(TAG, t, def) );
}
/**
* Inserts the template with the given default
* value at the given index.
*/
public void insertElementAt( ASN1Template t, ASN1Value def, int index )
{
insertElementAt( new Element(null, t, def), index );
}
/**
* Adds a sub-template with the given default value and implicit tag to
* the end of this SET template. For example, if the ASN.1 included:
* <pre>
* MySet ::= SET {
* item [0] IMPLICIT INTEGER DEFAULT (5),
* ... }
* </pre>
* the "item" element would be added to the MySet template with:
* <pre>
* mySet.addElement( new Tag(0), new SubType.Template(), new INTEGER(5) );
* </pre>
*/
public void addElement( Tag implicit, ASN1Template t, ASN1Value def ) {
addElement( new Element(implicit, t, def) );
}
/**
* Inserts the template with the given implicit tag and given default
* value at the given index.
*/
public void insertElementAt( Tag implicit, ASN1Template t, ASN1Value def,
int index )
{
insertElementAt( new Element(implicit, t, def), index );
}
/**
* Returns the implicit tag of the item stored at the given index.
* May be NULL if no implicit tag was specified.
*/
public Tag implicitTagAt(int index) {
return ((Element)elements.elementAt(index)).getImplicitTag();
}
/**
* Returns the sub-template stored at the given index.
*/
public ASN1Template templateAt(int index) {
return ((Element)elements.elementAt(index)).getTemplate();
}
/**
* Returns <code>true</code> if the sub-template at the given index
* is optional.
*/
public boolean isOptionalAt(int index) {
return ((Element)elements.elementAt(index)).isOptional();
}
private boolean isRepeatableAt(int index) {
return ((Element)elements.elementAt(index)).isRepeatable();
}
/**
* Returns the default value for the sub-template at the given index.
* May return NULL if no default value was specified.
*/
public ASN1Value defaultAt(int index) {
return ((Element)elements.elementAt(index)).getDefault();
}
/**
* Returns the number of elements in the SET.
*/
public int size() {
return elements.size();
}
public void removeAllElements() {
elements.removeAllElements();
}
public void removeElementAt(int index) {
elements.removeElementAt(index);
}
private Tag getTag() {
return SET.TAG;
}
/**
* Determines whether the given tag satisfies this template.
*/
public boolean tagMatch(Tag tag) {
return( tag.equals(SET.TAG) );
}
/**
* Decodes the input stream into a SET value.
*/
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(getTag(), istream);
}
/**
* Decodes the input stream into a SET value with the given implicit
* tag.
*/
public ASN1Value decode(Tag tag, InputStream istream)
throws IOException, InvalidBERException
{
try {
ASN1Header header = new ASN1Header(istream);
header.validate( tag, Form.CONSTRUCTED );
// remainingContent will be -1 for indefinite length encoding
long remainingContent = header.getContentLength();
SET set = new SET();
ASN1Header lookAhead;
boolean[] found = new boolean[ elements.size() ];
// while content remains, try to decode it
while( remainingContent > 0 || remainingContent == -1) {
// find out about the next item
lookAhead = ASN1Header.lookAhead(istream);
// if we found the end-of-content marker, we're done
if( lookAhead.isEOC() ) {
if( remainingContent != -1 ) {
throw new InvalidBERException("Unexpected end-of-content"+
"marker");
}
lookAhead = new ASN1Header(istream);
break;
}
// Find the element with the matching tag
int index = findElementByTag( lookAhead.getTag() );
if( index == -1 ) {
// element not found
throw new InvalidBERException("Unexpected Tag in SET: "+
lookAhead.getTag() );
}
Element e = (Element) elements.elementAt(index);
if( found[index] && ! e.isRepeatable() ) {
// element already found, and it's not repeatable
throw new InvalidBERException("Duplicate Tag in SET: "+
lookAhead.getTag() );
}
// mark this element as found
found[index] = true;
// Decode this element
ASN1Template t = e.getTemplate();
ASN1Value val;
CountingStream countstream = new CountingStream(istream);
if( e.getImplicitTag() == null ) {
val = t.decode(countstream);
} else {
val = t.decode(e.getImplicitTag(), countstream);
}
// Decrement remaining count
long len = countstream.getNumRead();
if( remainingContent != -1 ) {
if( remainingContent < len ) {
// this item went past the end of the SET
throw new InvalidBERException("Item went "+
(len-remainingContent)+" bytes past the end of"+
" the SET");
}
remainingContent -= len;
}
// Store this element in the SET
SET.Element se;
if( e.getImplicitTag() == null ) {
// no implicit tag
se = new SET.Element(val);
} else {
// there is an implicit tag
se = new SET.Element( e.getImplicitTag(), val );
}
set.addElement(se);
}
// We check for this after we read in each item, so this shouldn't
// happen
Assert._assert( remainingContent == 0 || remainingContent == -1);
// Deal with elements that weren't present.
int size = elements.size();
for(int i = 0; i < size; i++) {
if( !found[i] ) {
if( isOptionalAt(i) || isRepeatableAt(i) ) {
// no problem
} else if( defaultAt(i) != null ) {
set.addElement( new SET.Element(defaultAt(i)) );
} else {
throw new InvalidBERException("Field not found in SET");
}
}
}
return set;
} catch(InvalidBERException e) {
throw new InvalidBERException(e, "SET");
}
}
/**
* Returns the index in the vector of the type with this tag and class,
* or -1 if not found.
* lame linear search - but we're dealing with small numbers of elements,
* so it's probably not worth it to use a hashtable
*/
private int findElementByTag(Tag tag) {
int size = elements.size();
for( int i = 0; i < size ; i++ ) {
Element e = (Element) elements.elementAt(i);
if( e.tagMatch( tag ) ) {
// match!
return i;
}
}
// no match
return -1;
}
/**
* An element of a SET template.
*/
public static class Element {
public Element(Tag implicitTag, ASN1Template type, boolean optional)
{
this.type = type;
defaultVal = null;
this.optional = optional;
this.implicitTag = implicitTag;
}
public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal)
{
this.type = type;
this.defaultVal = defaultVal;
optional = false;
this.implicitTag = implicitTag;
}
// Repeatability is used for SET OF. It is package private.
private boolean repeatable;
void makeRepeatable() {
repeatable = true;
}
boolean isRepeatable() {
return repeatable;
}
private boolean optional;
public boolean isOptional() {
return optional;
}
private Tag implicitTag=null;
public Tag getImplicitTag() {
return implicitTag;
}
/**
* Determines whether the given tag satisfies this SET element.
*/
public boolean tagMatch(Tag tag) {
if( implicitTag != null ) {
return( implicitTag.equals(tag) );
} else {
return type.tagMatch(tag);
}
}
private ASN1Template type;
/**
* Returns the template for this element.
*/
public ASN1Template getTemplate() {
return type;
}
private ASN1Value defaultVal=null;
/**
* Returns the default value for this element, if one exists.
* Otherwise, returns null.
*/
public ASN1Value getDefault() {
return defaultVal;
}
}
} // End of SET.Template
/**
* A Template for decoding SET OF values.
* Use this if you have a SIZE qualifier on your SET OF.
* The SET will consume as many instances of type as it can, rather than
* stopping after the first one. This is equivalent to SIZE (0..MAX).
* If you need something more restrictive, you can look at what gets parsed
* and decide whether it's OK or not yourself.
*/
public static class OF_Template implements ASN1Template {
private OF_Template() { }
private Template template; // a normal SET template
/**
* Creates an OF_Template with the given type. For example:
* <pre>
* MySet ::= SET OF INTEGER;
* </pre>
* A <code>MySet</code> template would be constructed with:
* <pre>
* SET.OF_Template mySetTemplate = new SET.OF_Template( new
* INTEGER.Template() );
* </pre>
*/
public OF_Template(ASN1Template type) {
template = new Template();
Template.Element el = new Template.Element( null, type, false );
el.makeRepeatable();
template.addElement( el );
}
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
/**
* Decodes a <code>SET OF</code> from its BER encoding.
*/
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return template.decode(istream);
}
/**
* Decodes a <code>SET OF</code> with an implicit tag from its BER
* encoding.
*/
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
return template.decode(implicitTag, istream);
}
}
// Test driver for SET
public static void main(String args[]) {
try {
if(args.length > 0) {
FileInputStream fin = new FileInputStream( args[0] );
Template t = new SET.Template();
t.addElement(new Tag(0), new INTEGER.Template() );
t.addElement( new Tag(3), new INTEGER.Template() );
t.addOptionalElement( new Tag(4), new INTEGER.Template() );
t.addElement( new Tag(5), new INTEGER.Template(), new INTEGER(67) );
t.addElement( new Tag(29), new BOOLEAN.Template() );
t.addElement( new Tag(30), new BOOLEAN.Template(), new BOOLEAN(false) );
t.addElement( new Tag(1), new INTEGER.Template() );
t.addElement( new Tag(2), new INTEGER.Template() );
SET st = (SET) t.decode(new BufferedInputStream(fin) );
for(int i=0; i < st.size(); i++) {
ASN1Value v = st.elementAt(i);
if( v instanceof INTEGER ) {
INTEGER in = (INTEGER) st.elementAt(i);
System.out.println("INTEGER: "+in);
} else if( v instanceof BOOLEAN ) {
BOOLEAN bo = (BOOLEAN) st.elementAt(i);
System.out.println("BOOLEAN: "+bo);
} else {
System.out.println("Unknown value");
}
}
} else {
SET s = new SET();
s.addElement( new Tag(0), new INTEGER(255) );
s.addElement( new Tag(29), new BOOLEAN(true) );
s.addElement( new Tag(1), new INTEGER(-322) );
s.addElement( new Tag(2), new INTEGER(0) );
s.addElement( new Tag(3), new INTEGER("623423948273") );
s.encode(System.out);
}
} catch( Exception e ) {
e.printStackTrace();
}
}
}

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