Compare commits
2 Commits
JSS_4_0_BR
...
regalloc_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c43d4984f | ||
|
|
cfe021ff88 |
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal 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
|
||||
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal 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
|
||||
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal 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_
|
||||
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal 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
|
||||
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal 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));
|
||||
}
|
||||
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal 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
|
||||
|
||||
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal 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_
|
||||
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal 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"
|
||||
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal 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_
|
||||
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal 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_
|
||||
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal 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_
|
||||
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal 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_
|
||||
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal 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_
|
||||
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal 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"
|
||||
|
||||
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal 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_
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal 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)
|
||||
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal 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_
|
||||
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal 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;
|
||||
}
|
||||
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal 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_
|
||||
|
||||
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal 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
|
||||
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal 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_
|
||||
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal 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_ */
|
||||
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal 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_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal 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_
|
||||
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal 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_
|
||||
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal 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);
|
||||
}
|
||||
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal 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_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal 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
|
||||
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal 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_
|
||||
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal 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
|
||||
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal 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_
|
||||
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal 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_
|
||||
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal 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();
|
||||
}
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal 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_ */
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal 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;
|
||||
}
|
||||
|
||||
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal 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 ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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_
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ###
|
||||
### ###
|
||||
#######################################################################
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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:
|
||||
;+ *;
|
||||
;+};
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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). #
|
||||
#######################################################################
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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) );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user